OleDbConnection: How to open and close a connection using a function - c#

I have a function that connects to a Excel File:
public OleDbConnection connection;
public void eConnection(string srcString, string id)
{
conString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + srcString + "; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
connection = new OleDbConnection(conString);
connection.Open();
}
I want to create another function that will close this existing connection when called or invoke
This is what I have to try and close the existing connection:
public void eCloseConnection()
{
connection.Close();
}
How can I close the existing connection using a function that calls the same connection and closes it
How can I test to see if the connection is closed?

Don't do it like this. OleDbConnection implements the IDisposable interface should be disposed as soon as you are done using it, and the best way to do it is to use it as a local variable declared in a using statement:
public void DoStuffWithExcel(string srcString)
{
conString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + srcString + "; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
using(var connection = new OleDbConnection(conString))
{
connection.Open();
// do your stuff here...
}
}
The using statement ensures the connection will be disposed properly even if an exception occurs inside the using block.
This way is the best way to prevent memory leaks, as well as to use the connection pool.
From Microsoft docs page OLE DB, ODBC, and Oracle Connection Pooling:
We recommend that you always close or dispose of a connection when you are finished using it in order to return the connection to the pool. Connections that are not explicitly closed may not get returned to the pool. For example, a connection that has gone out of scope but that has not been explicitly closed will only be returned to the connection pool if the maximum pool size has been reached and the connection is still valid.

Don't keep a global object for a connection hidden inside a class. This adds more problems than the one solved. You should keep track how many time that code is called and how many connection it creates. And of course this makes a lot more complicated the closing part.
Instead the C# language offers a better approach to this kind of problem. An approach particularly suited for objects like a connection that requires unmanaged resources to be realeased to the OS as soon as possible.
You should instead use this approach both if you want to have a class that handles your connections or if you just want to open and use a connection
public static class DbUtility
{
public static OleDbConnection eConnection(string srcString)
{
conString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + srcString + "; Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
connection = new OleDbConnection(conString);
connection.Open();
return connection;
}
.... other static utilities
}
Now you can use your class in this way
string srcFile = #"d:\temp\myFile.xlsx";
using(OleDbConnection cn = DbUtility.eConnection(srcFile))
{
.. use your connection
} // <- at this point your connection is automatically closed and disposed.
The using keyword is of great help when you need to just destroy your disposable objects like a connection. In this way you don't keep a global object around when you don't need it.

Related

How to use a database connection class in my entire application

I have created a class for the MS Access database connection. It works fine on the majority of the forms within my Winforms app. However, I have a form where the user can add, edit or delete information from the database. I've constructed that part using a string, but when I remove the long database connection string I had there before and replace it with the class I created it throws an exception.
I've tried changing the code by removing the string, but I want to use the string method.
This is the code I have for the delete button click event
string con = (#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source =C:\Users\folder\Desktop\ApplicationFolder\AppName\bin\Debug\DataBase\DatabaseName.accdb");
string Query = "delete from Employees2 where EmployeeName = '" +
this.txtAdminFEmployee.Text + "' ; ";
OleDbConnection ConnectionString = new OleDbConnection(con);
OleDbCommand command = new OleDbCommand(Query, ConnectionString);
OleDbDataReader reader;
try
{
ConnectionString.Open();
reader = command.ExecuteReader();
DialogResult result = MessageBox.Show("Employee Deleted Successfully",
"Information",
MessageBoxButtons.OK, MessageBoxIcon.Information);
while (reader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
ConnectionString.Close();
This is the database class I created
using System.Data.OleDb;
namespace AppName
{
class OledbConnect
{
public OleDbConnection con;
public void Connection()
{
con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\DatabaseName.accdb");
}
}
}
I need to know how to use the database class in that string. I've tried different ways but nothing works. I am still new to c# and Google is not really returning anything I can use. Thanks
Your initial code works, but confusion is evident in the naming of variables.
string con = #"Provider = Microsoft.ACE.OLEDB.12.0; Data Source =C:\Users\folder\Desktop\ApplicationFolder\AppName\bin\Debug\DataBase\DatabaseName.accdb";
(I've taken the un-needed parentheses off the declaration; it's just a string.)
Calling that string 'con' is a bit confusing. I'd call it 'connectionString', or maybe 'cs' for short.
OleDbConnection ConnectionString = new OleDbConnection(con);
OleDbCommand command = new OleDbCommand(Query, ConnectionString);
OK, so you correctly create an OleDbConnection, passing the connection string (con) to its constructor. This is good. But you confusingly call it ConnectionString. It isn't the connection string; it's the connection, and your code thereafter uses it correctly.
So that works. Confusing for a human to read because of the mis-naming of variables, but the compiler doesn't care what their names are - it knows very well that ConectionString is an OleDbConnection and doesn't feel any of the cognitive dissonance that I do when I look at it.
If you rename the variables in the original code as I've suggested, and then copy that code into your class (BTW, I'd just call it DbConnection; it's current name is very close to another class name which might also be confusing), paying attention to what each statement does and what each variable represents then you should be good to go.

UWP connection string

I want to create a connection for my UWP and database. I want the uwp to send a value to the database.
MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;
myConnectionString = "server=127.0.0.1; uid = root;" + "pwd=root;database=test";
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString);
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
}
Is this the correct way to write the connection ? and where do I write this part of the coding at ?
enter image description here
Main page or any of my other page ? (scenario 1-3)
Your content looks right, I would try to use 'localhost' rather than ip.
var myConnection = new MySqlConnection();
myConnection.ConnectionString = "database=test;server=localhost;uid=root;pwd=root";
myConnection.Open();
More info see: https://dev.mysql.com/doc/dev/connector-net/6.10/html/P_MySql_Data_MySqlClient_MySqlConnection_ConnectionString.htm
I would also check here to see if you are providing enough info, which you are. https://www.connectionstrings.com/mysql/
In terms of connecting to the database, it depends. What type of application is this? Typically, database connections are made during the start of the application. If you are using Entity Framework, you'll want your Database Context to manage the connection (which is an entirely different topic).

which implementation is better for static db connection?

I know work with db.So i in my class have static object:
static private MySqlConnection conn = null;
public static Boolean postoji(String username, String password)
{
conn = new MySqlConnection("Server=127.0.0.1;Database=cs322;Uid=root;Password =; ");
Boolean rez=false;
try
{
conn.Open();...
In this class i have 5 mehtods,so i thinking,does is better to have this static object null,and initialization them in every method.Or have static object which is alrady created.
private MySqlConnection conn== new MySqlConnection("Server=127.0.0.1;Database=cs322;Uid=root;Password =; ");
and methods just use them.
I would say better would be have this connection string in your web.config or app.config and read it from there instead of defining your connection string in code. So that in future if your connection string needs change you know only one place change would present as well editing config file doesn't need you to re-publish your code.
You should be putting all the connection string in the configuration file. Below is the code sample for putting and reading it from confile fie.
web config file
<add name="ConnectionStringName" connectionString=127.0.0.1"; Initial Catalog=cs322; Integrated Security=True"/>
Also same time i would suggest to wrap your connection within the Using block like below example.
Reading code from code behind
using(MySqlConnetion connection = new MySqlConnetion(ConfigurationManager.ConnectionStrings["ConnectionStringName"].ToString()))
{
connection.open();
//setup and execute query
} //connection gets closed here
Here, once you exit the using block, the connection is closed.

Disable/Flush OleDbConnection Cache

I've been fighting with OleDbConnection for a while now trying to get it to not cache. Basically I am accessing a shared Access database, which is being written to from another application, and then I'm reading back values (having checked that it is flushed via the Last Write time and a subsequent 1 second delay).
Unfortunately, this is entirely unreliable.
I've been reading (and going insane) how to disable the connection pooling, and am subsequently, after each possible update, performing the following before reconnecting:
_connection.Close();
_connection.Dispose();
_connection = null;
OleDbConnection.ReleaseObjectPool();
GC.Collect();
In addition to this, the connection string disables connection pooling with OLE DB Services = -2. Finally, I have also changed PageTimeout to '10' in the registry for Jet 4.0.
All of these measures are unfortunately having no effect. Now the only thing I can think of doing is what is mentioned in this Microsoft KB Article, and call JRO.JetEngine.RefreshCache. The only issue with that is that it's argument is an ADODB.Connection. I'd rather not rewrite my whole database layer and where the records are being read by my software to use a legacy COM object just to have this functionality, but it appears that it may well be the only way.
My question is, whilst currently undergoing this task of rewriting to use ADODB (not even ADO.NET!), is it possible to disable the caching of an OleDbConnection?
Finally, I found a workaround: Use OdbcConnection instead of OleDbConnection.
This is the old code:
string mdbConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + mdbFile + ";OLE DB Services=-2";
using (OleDbConnection conn = new OleDbConnection(mdbConnectionString)) {
conn.Open();
//Do your query
}
And this is new one:
string mdbConnectionString = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=" + mdbFile;
using (OdbcConnection conn = new OdbcConnection(mdbConnectionString)) {
conn.Open();
//Do your query
}
All things work fine.
You might have some luck setting the ";Jet OLEDB:Flush Transaction Timeout" property to 0 or some low number.
See documentation.
32-bit application
In a 32-bit C# application, I'm doing this since years to refresh the cache:
public static void RefreshDatabaseCache(
string connectionString)
{
// The type of the ADODB connection. Used for dynamically creating.
var adodbType = Type.GetTypeFromProgID(#"ADODB.Connection");
// The main ADODB connection object.
var adodbInstance = Activator.CreateInstance(adodbType);
// --
// Open the connection.
adodbType.InvokeMember(
#"Open",
BindingFlags.InvokeMethod,
null,
adodbInstance,
new object[]
{
connectionString,
string.Empty,
string.Empty,
0
});
try
{
// The type of the JET engine. Used for dynamically creating.
var jroType = Type.GetTypeFromProgID(#"JRO.JetEngine");
// The main JET engine object.
var jroInstance = Activator.CreateInstance(jroType);
// Refresh the cache.
jroType.InvokeMember(
#"RefreshCache",
BindingFlags.InvokeMethod,
null,
jroInstance,
new[]
{
adodbInstance
});
}
finally
{
// Close the connection.
adodbType.InvokeMember(
#"Close",
BindingFlags.InvokeMethod,
null,
adodbInstance,
new object[]
{
});
}
}
I'm using OleDB in my whole application, just inside the above function, I'm using this "ADODB" thing.
64-bit application
In a 64-bit C# application I currently do know no way of doing this.

Access db, check if someone is using... (OLEDB/C#)

I have a problem with a threaded Client/Server application, I have a serversid that has a Access DB, and with one thread for each client, but I get a problem if both client threads asks to open the DB at the same time. Is there any way to check if the DB is in use (I know I can have a varible and keep controlling/setting that, but would like to avoid that. Here is an example connection
String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + dbPath + "'";
OleDbConnection connection = new OleDbConnection(connectionString);
OleDbCommand command;
connection.Open();
command = new OleDbCommand("UPDATE Client SET Online = " + online)
command.ExecuteNonQuery();
connection.Close();
Would really like some help!
/Nick
Per this http://www.connectionstrings.com/access-2007 you can set Exclusive=1 in connection string to grant that only one connection can use this database. All another trying will fail.

Categories