Which pattern is better for SqlConnection object? Which is better in performance?
Do you offer any other pattern?
class DataAccess1 : IDisposable
{
private SqlConnection connection;
public DataAccess1(string connectionString)
{
connection = new SqlConnection(connectionString);
}
public void Execute(string query)
{
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = query;
command.CommandType = CommandType.Text;
// ...
command.Connection.Open();
command.ExecuteNonQuery();
command.Connection.Close();
}
}
public void Dispose()
{
connection.Dispose();
}
}
VS
class DataAccess2 : IDisposable
{
private string connectionString;
public DataAccess2(string connectionString)
{
this.connectionString = connectionString;
}
public void Execute(string query)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = query;
command.CommandType = CommandType.Text;
// ...
command.Connection.Open();
command.ExecuteNonQuery();
command.Connection.Close();
}
}
public void Dispose()
{
}
}
There's no real way to answer this question. The short, canonical answer is that the connection should stay alive for the lifetime of your unit of work. Because we have no way of knowing how DataAccess is used (does it exist for the lifetime of your application, or do you instantiate it and dispose it whenever you do something?), it's impossible to give a concrete answer.
That being said, I would recommend the first pattern, but instantiate and dispose of your DataAccess object as needed; don't keep it around longer than necessary.
Suggest going with DataAccess2. It's a personal preference though. Some might even suggest your class be static. It'd be difficult to say that one is more performant than the other. You're on the path of IDisposable, which is great.
I'd be happy to read and maintain both styles shown above in your question.
Consider having your DAL be able to read the connection string from a .config as well, rather than exclusively allowing the value to be passed in the constructor.
public DataAccess2(string connStr)
{
this.connectionString = connStr;
}
public DataAccess2()
{
this.connectionString =
ConfigurationManager.ConnectionStrings["foo"].ConnectionString;
}
Consider wrapping your SqlCommand in a using as well.
using (var conn = new SqlConnection(connectionString))
{
using(var cmd = conn.CreateCommand())
{
}
}
I think it depends on how your DataAccess object is intended to be used, if it's used within a 'using' clause then the connection is guaranteed to be disposed of after it's done.
But in general I prefer the second pattern as the sql connection is created and disposed of within the Execute method so it's less likely to be left open when you forget to dispose of your DataAccess object.
Considering that sql connection can be a scarse resource I think every attempt should be made to ensure that they're not wasted.
The first will result in errors if you make concurrent calls.
The second will ensure you use a clean connection for each command resulting in more connections being made.
I agree with the statements above that it depends on the scenario for use, to get over the problem related to the first I have a wrapper that needs to use such a pattern so I set a field value boolean to show that a command is being executed on the connection already then "queue" the next command for execution.
There will of course be situations where you may prefer to use multiple connections ...
Related
I am using npgsql to connect to a CockroachDb cluster, in code with each command I want to execute I create a new connection and open it! I wonder if creating a private field variable holding the connection and opening it then closing it is much better than my current approach?
static async Task Task1()
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
new NpgsqlCommand("SQL Query here", conn).ExecuteNonQuery();
conn.Close();
}
}
static async Task Task2()
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
new NpgsqlCommand("SQL Query here", conn).ExecuteNonQuery();
conn.Close();
}
}and so on ....
Not really: although possible, it's a bit of an anti pattern.
NpgsqlConnection inherits from DbConnection. And DbConnection is a general Microsoft abstract class that represents a database connection, which is IDisposable.
So when putting the conn in a using block, you implicitly call Dispose as soon as it goes out of scope. This will close the connection and clean up other stuff. You don't have to separately call Close.
What you could do, is make a general wrapper like
public static async Task NonQueryCommand(string command)
{
using (var conn = new NpgsqlConnection(connString))
{
conn.Open();
using (var cmd = new NpgsqlCommand(command, conn) // Also IDisposable
{
cmd.ExecuteNonQuery();
}
}
}
But you could lose all flexibility that way (the repository pattern can be bad if not used correctly).
Also check the official resources
I am writing SQL Server integration tests using xUnit.
My tests look like this:
[Fact]
public void Test()
{
using (IDbConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
connection.Query(#$"...");
//DO SOMETHING
}
}
Since I am planning to create multiple tests in the same class I was trying to avoid creating a new SqlConnection every time. I know that xUnit framework per se creates an instance of the class per each running test inside it.
This means I could make the creation of the SqlConnection in the constructor since anyway a new one will be created every time a new test run.
The problem is disposing it. Is it good practice or do you see any problem in disposing manually the SqlConnection at the end of each test?
Such as:
public class MyTestClass
{
private const string _connectionString = "...";
private readonly IDbConnection _connection;
public MyTestClass()
{
_connection = new SqlConnection(_connectionString));
}
[Fact]
public void Test()
{
_connection.Open();
_connection.Query(#$"...");
//DO SOMETHING
_connection.Dispose();
}
}
I was trying to avoid creating a new SqlConnection every time.
It's okay to create and dispose a new SqlConnection over and over. The connection instance is disposed, but the underlying connection is pooled. Under the hood it may actually use the same connection repeatedly without closing it, and that's okay.
See SQL Server Connection Pooling.
So if that's your concern, don't worry. What you are doing in the first example is completely harmless. And however your code is structured, if you're creating a new connection when you need it, using it, and disposing it, that's fine. You can do that all day long.
If what concerns you is the repetitive code, I find this helpful. I often have a class like this in my unit tests:
static class SqlExecution
{
public static void ExecuteSql(string sql)
{
using (var connection = new SqlConnection(GetConnectionString()))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
public static T ExecuteScalar<T>(string sql)
{
using (var connection = new SqlConnection(GetConnectionString()))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
return (T)command.ExecuteScalar();
}
}
}
public static string GetConnectionString()
{
// This may vary
}
}
How you obtain the connection string may vary, which is why I left that method empty. It might be a configuration file, or it could be hard-coded.
This covers the common scenarios of executing something and retrieving a value, and allows me to keep all the repetitive database code out of my tests. Within the test is just one line:
SqlExecution.ExecuteSql("UPDATE WHATEVER");
You can also use dependency injection with xUnit, so you could write something as an instance class and inject it. But I doubt that it's worth the effort.
If I find myself writing more and more repetitive code then I might add test-specific methods. For example the test class might have a method that executes a certain stored procedure or formats arguments into a query and executes it.
You can also do dependency injection with xUnit so that dependencies are injected into the class like with any other class. There are lots of answers about this. You may find it useful. Maybe it's the reason why you're using xUnit. But something simpler might get the job done.
Someone is bound to say that unit tests shouldn't talk to the database. And they're mostly right. But it doesn't matter. Sometimes we have to do it anyway. Maybe the code we need
to unit test is a stored procedure, and executing it from a unit test and verifying the
results is the simplest way to do that.
Someone else might say that we shouldn't have logic in the database that needs testing, and I agree with them too. But we don't always have that choice. If I have to put logic in SQL I still want to test it, and writing a unit test is usually the easiest way. (We can call it an "integration test" if it makes anyone happy.)
There's a couple different things at play here. First, SqlConnection uses connection pooling so it should be fine to create/dispose the connections within a single test.
Having said that disposing of the connections on a per test class basis would also be doable. XUnit will dispose of test classes that are IDisposable. So either would work. I'd suggest it's cleaner to create/dispose them within the test.
public class MyTestClass : IDisposable
{
const string ConnectionStr = "";
SqlConnection conn;
public MyTestClass()
{
this.conn = new SqlConnection(ConnectionStr);
}
public void Dispose()
{
this.conn?.Dispose();
this.conn = null;
}
public void Test()
{
using (var conn = new SqlConnection(ConnectionStr))
{
}
}
}
I'm writing a desktop application using C# winforms and MSSQL server 2012. there are several classes exit in this application that need to connect to database and all uisng ADO.Net. this is on of my classes :
class Prices
{
private int id = 0;
public int Id
{
get { return id; }
set { id = value; }
}
private string materialName = string.Empty;
......
......
......
public void updateMaterialPrice()
{
string conString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString();
using (SqlConnection sqlCon = new SqlConnection(conString))
using (SqlCommand sqlCmd = new SqlCommand("spUpdateMaterialPrice", sqlCon))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("materialName",MaterialName);
sqlCmd.Parameters.AddWithValue("unitPrice", Price);
sqlCmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
sqlCmd.Parameters.AddWithValue("protein", Proterin);
sqlCmd.Parameters.AddWithValue("fat", Fat);
sqlCmd.Parameters.AddWithValue("humidity", Humadity);
sqlCmd.Parameters.AddWithValue("minerlas", Minerlas);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
sqlCon.Dispose();
}
}
public void addMaterial()
{
string ConString = ConfigurationManager.ConnectionStrings["secaloFormulaCS"].ToString();
using(SqlConnection sqlCon = new SqlConnection(ConString))
using(SqlCommand sqlCmd = new SqlCommand("spAddMaterial",sqlCon))
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("materialName", MaterialName);
sqlCmd.Parameters.AddWithValue("unitPrice",Price);
sqlCmd.Parameters.AddWithValue("carbohydrate",Carbohydrtate);
sqlCmd.Parameters.AddWithValue("proterin", Proterin);
sqlCmd.Parameters.AddWithValue("fat",Fat);
sqlCmd.Parameters.AddWithValue("humidity", Humadity);
sqlCmd.Parameters.AddWithValue("minerals",Minerlas);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
sqlCon.Dispose();
}
as you can see in addMterial() and updateMaterialPrice() i use the same code to connect to database and call a stored procedure and this is repeated for several times in my other classes. how can i prevent this code repetition ? is it any way to just write the code needed for connection and query the database one time and reuse it several times according to situation needed ?
I use a Factory pattern for my Database connections, this means I never have to open a SqlConnection or pass connection strings around my program.
Here is an example for the method I use to run a query that returns multiple rows.
I would call the method from a "makeObject" method that would turn this datatable into an object.
public static class DB
{
private static readonly string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
/// <summary>
/// Use when returning data from multiple rows
/// </summary>
/// <param name="sql">query</param>
/// <param name="parameters">declared parameters</param>
/// <returns>datatable of db rows</returns>
public static DataTable GetDataTable(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = sql;
if (parameters != null)
{
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
}
using (DbDataAdapter adapter = factory.CreateDataAdapter())
{
adapter.SelectCommand = command;
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}
}
catch (Exception)
{
throw;
}
}
}
Well, you could make a helper method to prepare the command for you, or at least fill the parameters, eg.
void PrepareParameters(SqlCommand cmd)
{
cmd.Parameters.AddWithValue("materialName",MaterialName);
cmd.Parameters.AddWithValue("unitPrice", Price);
cmd.Parameters.AddWithValue("carbohydrate", Carbohydrtate);
cmd.Parameters.AddWithValue("protein", Proterin);
cmd.Parameters.AddWithValue("fat", Fat);
cmd.Parameters.AddWithValue("humidity", Humadity);
cmd.Parameters.AddWithValue("minerlas", Minerlas);
}
Ideally, unless you want to use a ready ORM like Entity Framework (usually a good idea), you'd create a few abstract classes to handle these kinds of things, so that you'll save on code reuse.
For example, the PrepareParameters method could be abstract, and there could be an abstract property that returns the name of the SP to update, create or delete (or better yet, you could follow a naming scheme so that you'd only need one name). Then you could write 99% of the logic in the abstract base classes, and only prepare the parameters in the actual derived classes, thus cutting code repetition a lot.
Some options are as follows:
Write a SqlHelper class which does the repetitive grunt work of executing a stored procedure. (especially ExecuteNonQuery ones, so that you don't need to worry about return types.)
e.g.
public void ExecuteQuery(string sprocName, SqlParamater[] parameters)
{
// initialize connection
// construct command with sprocName and parameters
// ExecuteNonQuery
}
Use Linq2Sql
This is an excellent quick ORM tool which simplies data access to a great deal.
Use Entity Framework
This is an increasingly used ORM tool.
All of the above approaches have their pros/cons. You need to weight them & select the right method.
I'm looking to figure out the best way to execute a database query using the least amount of boilerplate code. The method suggested in the SqlCommand documentation:
private static void ReadOrderData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
}
}
finally
{
reader.Close();
}
}
}
mostly consists of code that would have to be repeated in every method that interacts with the database.
I'm already in the habit of factoring out the establishment of a connection, which would yield code more like the following. (I'm also modifying it so that it returns data, in order to make the example a bit less trivial.)
private SQLConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
private List<int> ReadOrderData()
{
using(var connection = CreateConnection())
using(var command = connection.CreateCommand())
{
command.CommandText = "SELECT OrderID FROM dbo.Orders;";
using(var reader = command.ExecuteReader())
{
var results = new List<int>();
while(reader.Read()) results.Add(reader.GetInt32(0));
return results;
}
}
}
That's an improvement, but there's still enough boilerplate to nag at me. Can this be reduced further? In particular, I'd like to do something about the first two lines of the procedure. I don't feel like the method should be in charge of creating the SqlCommand. It's a tiny piece of repetition as it is in the example, but it seems to grow if transactions are being managed manually or timeouts are being altered or anything like that.
edit: Assume, at least hypothetically, there's going to have to be a bunch of different types of data being returned. And consequently the solution can't be just one one-size-fits-all method, there will have to be a few different ones depending, at minimum, on whether ExecuteNonQuery, ExecuteScalar, ExecuteReader, ExecuteReaderAsync, or any of the others are being called. I'd like to cut down on the repetition among those.
Tried Dapper?
Granted this doesn't get you a DataReader but you might just prefer it this way once you've tried it.
It's about the lightest-weight an ORM can be while still being called an ORM. No more methods to map between DataReader and strong types for me.
Used right here on all the StackExchange sites.
using (var conn = new SqlConnection(cs))
{
var dogs = connection.Query("select name, age from dogs");
foreach (dynamic dog in dogs)
{
Console.WriteLine("{0} age {1}", dog.name, dog.age);
}
}
or
using (var conn = new SqlConnection(cs))
{
var dogs = connection.Query<Dog>("select Name, Age from dogs");
foreach (Dog dog in dogs)
{
Console.WriteLine("{0} age {1}", dog.Name, dog.Age);
}
}
class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
If you want to roll data access on your own, this pattern of help methods could be one way to remove duplication:
private List<int> ReadOrderData()
{
return ExecuteList<int>("SELECT OrderID FROM dbo.Orders;",
x => x.GetInt32("orderId")).ToList();
}
private IEnumerable<T> ExecuteList(string query,
Func<IDataRecord, T> entityCreator)
{
using(var connection = CreateConnection())
using(var command = connection.CreateCommand())
{
command.CommandText = query;
connection.Open();
using(var reader = command.ExecuteReader())
{
while(reader.Read())
yield return entityCreator(reader);
}
}
}
You'll have to add support for parameters and this might not compile, but the pattern is what I'm trying to illustrate.
What I typically do is use a custom class that I wrote a while back that accepts a SQL string, and optionally a list of parameters and it returns a DataTable.
Since the thing that changes between invocations is typically just the SQL that is optimal IMHO.
If you truly do need to use a DataReader you can do something like this:
public void ExecuteWithDataReader(string sql, Action<DataReader> stuffToDo) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
using (SqlCommand command = new SqlCommand(sql, connection)) {
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
try {
while (reader.Read()) {
stuffToDo(reader);
}
}
finally {
reader.Close();
}
}
}
}
}
private static void ReadOrderData(string connectionString) {
string sql = "SELECT OrderID, CustomerID FROM dbo.Orders;";
ExecuteWithDataReader(sql, r => Console.WriteLine(String.Format("{0}, {1}", r[0], r[1])));
}
The first two line are the most important thing you need...
but if you still wish to do it, you can turn them to a database handler class, yes it will become more of code, but in refactoring concept, every thing will move to the related topic...
try to write a singleton class, that receive a command and do action, so return result of type SqlDataReader reader...
Doing this in comments was too much.
I would suggest that the boilerplate code around
using(conn = new sqlconnection)
using(cmd = new sqlcommand) {
// blah blah blah
}
isn't something to be lightly removed and instead would encourage that you keep it exactly where it's at. Resources, especially unmanaged ones, should be opened and released at the closest point to execution as possible IMHO.
In no small part due to the ease with which other developers will fail to follow the appropriate clean up conventions.
If you do something like
private SQLConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
Then you are inviting another programmer to call this method and completely fail to release the resource as soon as the query is executed. I don't know what kind of app you are building, but in a web app such a thing will lead to memory / connection / resource errors of types that are difficult to debug, unless you've been through it before.
Instead, I'd suggest you look into a lightweight ORM such as Dapper.net or similar to see how they approached it. I don't use dapper, but I hear it's pretty good. The reason I don't use it is simply that we don't allow inline sql to be executed against our databases (but that's a very different conversation).
Here's our standard:
public static DataTable StatisticsGet( Guid tenantId ) {
DataTable result = new DataTable();
result.Locale = CultureInfo.CurrentCulture;
Database db = DatabaseFactory.CreateDatabase(DatabaseType.Clients.ToString());
using (DbCommand dbCommand = db.GetStoredProcCommand("reg.StatsGet")) {
db.AddInParameter(dbCommand, "TenantId", DbType.Guid, tenantId);
result.Load(db.ExecuteReader(dbCommand));
} // using dbCommand
return result;
} // method::StatisticsGet
We make heavy use of Enterprise Library. It's short, simple and to the point and very well tested. This method just returns a datatable but you could easily have it return an object collection.. or nothing.
This is interesting (to me anyway), and I'd like to see if anyone has a good answer and explanation for this behavior.
Say you have a singleton database object (or static database object), and you have it stored in a class Foo.
public class Foo
{
public static SqlConnection DBConn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
}
Then, lets say that you are cognizant of the usefulness of calling and disposing your connection (pretend for this example that its a one-time use for purposes of illustration). So you decide to use a 'using' block to take care of the Dispose() call.
using (SqlConnection conn = Foo.DBConn)
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SP_YOUR_PROC";
cmd.ExecuteNonQuery();
}
conn.Close();
}
This fails, throwing an exception on the call to open the connection, stating that the "ConnectionString property is not initialized". It's not an issue with pulling the connection string from the app.config/web.config. When you investigate in a debug session you see that Foo.DBConn is not null, but contains empty properties.
Why is this?
A little out of topic and not really answering your question but why using a singleton for SqlConnection when ADO.NET already uses a connection pool? Your code could have very well looked like this:
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SP_YOUR_PROC";
cmd.ExecuteNonQuery();
}
And one less thing to worry about in your program: connection lifecycle
Perhaps you do not have the corresponding connectionStrings node in you web/app.config?
<connectionStrings>
<add name="BAR"
connectionString="Data Source=localhost\sqlexpress;Initial Catalog=mydatabase;User Id=myuser;Password=mypassword;" />
The static field is evaluated sometime before it is used (not deterministically). See beforefieldinit for more detail. So the system may not be ready for creating an SQL-connection when it is called or maybe even properly create the static field after you use it.
Additionally, how would you handle a second SQL-command after you closed the first one? I don't know exactly how SqlConnection works, but after closing (note that this cals Dispose) and disposing the connection, your static Foo.DBConn should be gone, i.e. it won't be reevaluated.
If you want to keep your basic infrastructure, I would replace the static field with a static property which returns a new SqlConnection on get:
public static SqlConnection DBConn
{
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["BAR"].ConnectionString);
}
}