I'm maintaining an existing C# application which uses classic ADO.NET as a data access technology.The existing code creates a new instance of the SqlConnection and SqlCommand objects EVERY single time some interaction with the database is required. To make things simpler I wrote a little class to simplify this process to prevemt code repetition but I'm not an expert at ADO.NET so I wanted to ask if you can review my code and let me know if I missed any ADO.NET best practices or if the code below may impact DB operations negatively in anyway:
using System;
using System.Data;
using System.Data.SqlClient;
namespace MyApp.DataAccess
{
public class DataAccessLayer : IDisposable
{
private SqlConnection _connection = new SqlConnection();
private SqlCommand _command = new SqlCommand();
public string ConnectionString
{
get { return DBConfig.ConnectionString; }
}
public SqlCommand Command
{
get { return _command; }
set { _command = value; }
}
public SqlConnection SQLConnection
{
get
{
if(_connection == null || _connection.State == ConnectionState.Closed)
{
_connection = new SqlConnection(ConnectionString);
_connection.Open();
}
return _connection;
}
}
public void SetCommand(string commandText,CommandType commandType)
{
_command = new SqlCommand(commandText, SQLConnection);
_command.CommandType = commandType;
}
public void Dispose()
{
if (_connection != null)
_connection.Dispose();
if (_command != null)
_command.Dispose();
}
}
}
As Tim explained, I would rather code this with the using statement. This will automatically close and dispose your SqlConnection instance.
Take a look at this example here from the MSDN page about the SqlConnection class:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Do work here; connection closed on following line.
}
And what model_dialog explained, is also correct.
If you invoke the Open method on the SqlConnection class the framework will not necesserily really open a new connection.
Instead it will check whether there is already an appropiate connection available in the connection pool. It does this by checking the connection string. If it founds a suitable connection, the connection pool will just return this connection with almost no performance impact. The connection pool is a catching component for SqlConnections so to speak.
See here for more details: SQL Server Connection Pooling (ADO.NET)
Related
This question already has answers here:
What is the C# Using block and why should I use it? [duplicate]
(9 answers)
Closed 5 years ago.
I wonder that what is the difference between ;
using (var con = new OracleConnection(oradb))
{
con.Open();
// Do sth.
con.Dispose();
con.Close();
}
from this;
oradb = ConString;
OracleConnection con = new OracleConnection(oradb))
con.Open();
// Do Sth.
con.Dispose();
con.Close();
Both of them works for me, However didn't understand the basic behind of this.
Which one should i use ?
If we look at the decompiled code:
using System;
public class C {
public void M() {
using(var conn = new Connection()){
}
}
}
is turned into:
public class C
{
public void M()
{
Connection connection = new Connection();
try
{
}
finally
{
if (connection != null)
{
((IDisposable)connection).Dispose();
}
}
}
}
Unlike the code without a using block, the connection will be disposed even if the exception is thrown.
A bit more reading about the using could be found here (C# Reference doc)
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.
Using ensures that the connection is always disposed. If you dispose it manually it can happen that part of the code is never executed at all.
With using, disposing of connection is handled automaticaly :
using (var con = new OracleConnection(oradb))
{
con.Open();
// Do sth.
con.Close();
} // ok
using with dispose your connection object automatically. you dont have to do it manually.
using(var con = new OracleConnection(oradb))
{
con.Open();
}
is equal to (some what similar , you can use ILDSAM on your code and check)
OracleConnectioncon = null;
try
{
con = new OracleConnection(oradb);
con.Open();
}
finally
{
con.Disponse();
}
you can clear you concept by reading : Dispose Pattern
I have created a class in my program to handle database connection. This class includes a method named OpenConnection() to open the connection to the database. I'm not convinced that my program meets the standard of clean code. Here is the method.
public void OpenConnection()
{
if(connection==null || connection.State != Connection.Open)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
}
}
This method works okay but I just want to make sure if this is a safe way and I am not exploiting my program in any way. Thank You in advance
Update
I also added the following methods in the class to close the connection and dispose it.
public void CloseConnection()
{
if (dbconnect != null | dbconnect.State != ConnectionState.Closed)
{
dbconnect.Close();
}
}
//Here the IDsiposable method is implemented
public void Dispose()
{
CloseConnection();
}
You can use using clause and it's going to handle the Dispose automatically.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#EmployeeID", 123));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
connection.close();
}
Your solution as coded seems ok if you add the cases suggested in this answer and if it's meant to be used on a single thread and within a very limited scope. That said it appears like you are gearing up to use this class as a parameter across many method calls because you want to
mix business logic and persistence concerns
or share an instance in such a way that other methods don't have to be concerned about whether to open the connection (e.g. a higher call in the call stack has not yet called Open) or not (e.g. a prior call in the call stack did open the connection (what we'd call an "ambient" connection)).
Either of these strategies usually leads to trouble. It's better to keep the scope small, where you know the connection is open and when to close it:
using (var connection = new OracleConnection(...))
{
connection.Open();
...
}
When you have this small scope, your abstraction now provides no value.
You have a possible resource leak owing to the fact that OracleConnection implements IDisposable. Also, calling close on a connection in ConnectionState.Executing or Fetching could be bad as it will rollback all uncommitted transactions.
public void OpenConnection()
{
if (connection == null)
{
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
switch (connection.State)
{
case ConnectionState.Closed:
case ConnectionState.Broken:
connection.Close();
connection.Dispose();
connection = new OracleConnection(this.connectionString);
connection.Open();
return;
}
}
Is it necessary to separately dispose of a SqlConnection as well as a SqlCommand?
I'm doing some maintenance work on an application and found the following code:
public void CallStoredProc(string storedProcName)
{
using (SqlCommand command = new SqlCommand(storedProcName, CreateConnection()))
{
command.CommandType = CommandType.StoredProcedure;
command.Connection.Open();
// Additional code here.
command.ExecuteNonQuery();
}
}
Will this clean up the SqlConnection properly, under normal circumstances as well as if there is an error? Or would we have to alter the code to something like:
public void CallStoredProc(string storedProcName)
{
using (SqlConnection connection = CreateConnection())
{
using (SqlCommand command = new SqlCommand(storedProcName, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Connection.Open();
// Additional code here.
command.ExecuteNonQuery();
}
}
}
yes , it is necessary to dispose the sqlconnection and sqlcommand object after your piece of code gets executed.
Now, there are two ways by which you can achieve this:
Write your code in using statement which will take care of disposing the objects, as sqlconnection and sqlcommand implements the IDisposable interface which takes care of disposing the objects..
by calling .close() method explicitly on sqlconnection object.
Yes, you will have to dispose (of) the connection separately. You can also see this in the source code: SqlCommand.Dispose() does not close or dispose the connection it uses (by the way, that would be bad anyway as you could not execute multiple commands with the same connection).
I have a program in C# where I created various class, and all of them need to make calls to the database. So I decided to create a static class that handles all the calls to allow me to apply far-reaching changes very easily. Within that class I have functions that call the various parts of SqlCommand (ExecuteReader(), etc) I finally got tired of rewriting all the connection code, and abstracted it out to another function called getSqlCommand() which just returns an initialized SqlCommand which I use to perform the various commands. I've chosen to not pass the SqlCommand back to the other programs (though it is a public method in case I need it) because there is some pre-processing if you will that I may do before I had the results back to the program.
My question is, if/when the SqlConnection closes? Since it is being passed back as a return value in a SqlCommand, will it be left open? and if so, can I close it? Here is some code (slightly stripped down) so you can see what I am doing, thanks in advance!
The function to create the SqlCommand:
public static SqlCommand GetSqlCommand(string query)
{
using (SqlConnection dbConnection = new SqlConnection( SQLConn )) {
dbConnection.Open();
SqlCommand cmd = new SqlCommand( query, dbConnection );
cmd.CommandTimeout = 0;
return cmd;
}
}
An example of the usage of the command in the static class:
public static SqlDataReader executeReader( string query )
{
try {
return GetSqlCommand(query).ExecuteReader();
} catch (SqlException) {
//Notify User and Resolve Error
}
return null;
}
A SqlConnection is closed when you call Dispose. Exiting the using block does that. The connection will be closed.
That's all there is to it. It will not magically stay open because ADO.NET does not know and cannot find out that you returned the connection object.
Move the connection out of the GetSqlCommand method. Pass the connection object into that method. GetSqlCommand has no business in creating a connection. It should take a connection, use it, but not close it.
The connection closes before the code exits the GetSqlCommand method. That means that the command object that it returns is useless.
The using construct creates a try ... finally block, where it disposes the connection at the end of the block. As disposing the connection also closes it, the connection is already closed before the command object is returned from the method to the caller.
The using keyword is equivalent to use try finally, and within the finally block your connexion will be disposed
SqlConnection dbConnection = new SqlConnection( SQLConn );
try
{
dbConnection.Open();
SqlCommand cmd = new SqlCommand( query, dbConnection );
cmd.CommandTimeout = 0;
return cmd;
}
catch(Exception ex)
{
}
finally
{
dbConnection.Dispose();
}
And even if there is a return statement inside a try block , the block finally will always be executed
I have created a generic Database handler class for my app.
Im using a local database so SqlCeConnection class is being used here.
What I would like to do is test that the Connection string is valid, so update the connection status to the user before I execute connection.Open();
lets say
SqlCeConnection conn = new SqlCeConnection(connectionString);
//so far we have only created the connection, but not tried to open it
//Would be nice to update the UI to say that conn is OK
conn.testConnection();
conn.Open();
I was thinking of writing a method that attempts to open then close the connection, am I right in thinking this or is there a better way.
testing for connectivity adds extra overhead. why not directly open connection and put the code inside Try-Catch
try
{
conn.Open();
}
catch(SqlCeException ex)
{
// output the error to see what's going on
MessageBox.Show(ex.Message);
}
You can use DbConnectionStringBuilder with property ConnectionString, it will throw exception if connection string is not correct format:
public static class Extension
{
public static void TestConnection(this DbConnection connection)
{
var builder = new DbConnectionStringBuilder
{
ConnectionString = connection.ConnectionString
};
}
}
With this way you don't need to really open connection to database.