public class db
{
public static string connectionString =
WebConfigurationManager.ConnectionStrings["connectString"].ConnectionString;
public static SqlConnection OpenConnection()
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
}
I see code like this and it screams WRONG! It's for an ASP.NET (2.0). I understand it to be wrong.
For one you shouldn't open the SqlConnection and return it and two why would you make a static SqlConnection? Won't that create problems if multiple people are trying use it at the same time?
What is static is OpenConnection() the Method which returns the connection. A new connection gets returned each time however (the assumption is that caller will be in charge of disposing of this connection object when appropriate).
In other words, the db class shown is not a singleton at all. The confusion may arise from the fact that one does not need to instantiate an instance of db in order to use its OpenConnection() method (since it is static), and the rest of the code may contain multiple snippets like
myConn = db.OpenConnection();
-- then do something with myConn
I'm not 100% sure what the question is, but to answer this
Won't that create problems if multiple
people are trying use it at the same
time?
no, there wouldn't be problems because each call to OpenConnection() constructs a new SqlConnection instance. That doesn't mean the code isn't garbage for other reasons. I at least hope calls to this method look something like this:
using(var conn = db.OpenConnection())
{
// stuff
}
You can't just say "Screams of being wrong" and then apply the term "Singleton" incorrectly. Why is a single static connection a poor approach? It you do not recreate it each time, then your entire application can share the connection. Do you need to create, open and close for each frigg'n sql call, that screams of stupid. Either way ADO should manage this.
Connection objects must be scoped to the method that executes the transaction.
Sharing the same connection object between threads will corrupt the connection pool.
See this question on SQLDataReader.GetOrdinal() fails rarely with IndexOutOfRange.
Related
I'm not sure if i'm just having a dumb moment here or I generally do not understand but can someone explain to me why this will run:
using System.Data.SqlClient;
using System.Configuration;
public void SomeMethod()
{
using(SqlConnection dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString))
{
using(SqlCommand qry = new SqlCommand(someSqlString, dbConnection))
{
dbConnection.Open();
using(SqlDataReader reader = qry.ExecuteReader())
{
...
}
}
}
}
and this will not run throwing an InvalidOperationException (The ConnectionString property has not been initialized) when it hits dbConnection.Open():
using System.Data.SqlClient;
using System.Configuration;
private SqlConnection dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString);
public void SomeMethod()
{
using(dbConnection)
{
using(SqlCommand qry = new SqlCommand(someSqlString, dbConnection))
{
dbConnection.Open();
using(SqlDataReader reader = qry.ExecuteReader())
{
...
}
}
}
}
The second example will run (at least it should)... but only the first time you call SomeMethod(). This is because after the first call to the method, you have Dispose()'d the connection object.
ADO.Net has a built-in feature called Connection Pooling that intelligently re-uses the underlying database connection resources. For the most part, you should not try to use the same Dbconnection object over and over. Instead, just re-use the connection string, create the connection objects as you need them, and Dispose() of them as soon as possible when done. Otherwise, you are conflicting with the built-in connection pooling and making things worse, rather than better.
In other words, the first sample is the correct way to do this. It's faster and more efficient than the second, even though the second seems to save you an object allocation here and there.
About the only time you should try to re-use a connection object is when you're going to have a bunch of queries in a tight loop, such that you might open the connection once, execute a bunch of queries one after the other, and then close it when you've finished the whole batch. And even then, most of the time when I've seen this the code was better off refactored in some way to group the sql statements into a single batch.
MSDN explains:
You can instantiate the resource object and then pass the variable to
the using statement, but this is not a best practice. In this case,
the object remains in scope after control leaves the using block even
though it will probably no longer have access to its unmanaged
resources. In other words, it will no longer be fully initialized. If
you try to use the object outside the using block, you risk causing an
exception to be thrown. For this reason, it is generally better to
instantiate the object in the using statement and limit its scope to
the using block.
So, to simplify it...
using statement ensures that the object will be disposed after code block is executed and will ensure the object will go out of scope. So, in your second example, you're using it wrong, and the connection is no longer managed so it behavies unpredictably.
Sometimes I see people like to dispose just anything after use regardless of how frequently they're being used (probably not related to SQLite question, but I am dealing with SQLite as of now, I'm puzzled) -- or perhaps I am mistaken. This has caused a massive confusion for me.
For example (taken from elsewhere):
using(var con = new SQLiteConnection(conString))
using(var cmd = new SQLiteCommand(con))
{
con.Open();
// ...
} // also closes the connection
My question is, should I store the SQLiteConnection and SQLiteCommand objects in the field, and use the method .Open(), .Close() to handle the database connection without disposing them at all until application termination -- or dispose them into the Garbage Collection like it's not really an elegant idea in my perspective?
Edit: If one says dispose, then why? I need better answers, I need the true reason why, not because of pooling, and whatnot. I need to know what exact problems could arise other than human-prone errors, and provide an example or perhaps a link to the example.
For example the class field:
private static SQLiteConnection sQLiteConnection; /// <summary>SQLiteConnection.</summary>
public static SQLiteConnection SQLiteConnection { get { return sQLiteConnection; } }
private static SQLiteCommand sQLiteCommand; /// <summary>SQLiteCommand.</summary>
public static SQLiteCommand SQLiteCommand { get { return sQLiteCommand; } }
Where the private fields are initialized with a private method, and the objects are to be reused without disposing them; Hence the read-only properties.
Edit 2: For clearer clarification, are you people misreading? I am saying "reusing". Which means one is created, and stored somewhere in the field to be reused. I am storing it in the static field in a static class to be reused until the application is closed. Tell me, why do I have to dispose it?
Why, do, I, have, to, dispose, it? If, I, were, to, "reuse", it? Why?
Connections are pooled by .NET, so creating them generally isn't an expensive operation. Using the "standard" approach is generally much cleaner that trying to keep track of if a connection is open or closed, etc.
Unless you have measurable problems with connection I would stick with the idomatic approach of creating them, using them, and disposing of them.
My question might be silly or may not be a question at all, but here it goes..
I am performing quite some database operations in my ASP.net MVC project where I am creating two objects each and every time namely, SqlConnection and SqlCommand.
I have shown an example below
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("sRegisterUser", connection))
{
I am doing all these different operations inside one class under different methods.
My question is how can I reduce the creation of these objects each and every time? How can I create them globally
PS: sRegisterUser is a stored procedure, like wise other methods use different procedures which gets different values as parameters.
Please help me out.
Thanks for any help in advance.
The answer is, don't. You do not want to share these objects, you are using them appropriately.
You don't. You either keep the object alive, which is bad. Or you dispose it the way you should, and currently do.
So, why do you have use using?
Since using is necessary for disposing the handles in Windows.
You could also write this, which is similar to using using:
SqlConnection connection = new SqlConnection(connectionString);
connection.Close();
connection.Dispose();
using also disposes when the code above throws an error. Using using is actually the shortest way to code this.
So the error-save version should be:
SqlConnection connection;
try
{
connection = new SqlConnection(connectionString);
...
connection.Close();
}
finally
{
connection.Dispose();
}
As others already said, there is nothing wrong with what you're doing right now. ADO.NET objects are meant to be used and disposed of. As a rule of thumb you should create them as late as possible and dispose of them as soon as possible.
With that being said, I understand what you're trying to do here and I do have a few ideas you might be interested in for making your life easier while keeping good programming practices.
If you want to make the code more concise you can chain using statements:
using (var cn = new SqlConnection(yourConnectionString))
using (var cmd = new SqlCommand(yourQuery, cn))
{
// do stuff
}
The IDE will not try to indent the second block, making it easier on you to read.
You can also create an abstraction layer for your procedure:
public static class Procedures
{
public static void RegisterUser() // add whatever parameters you need
{
using (var cn = new SqlConnection(yourConnectionString))
using (var cmd = new SqlCommand(yourQuery, cn))
{
// do stuff
}
}
}
From then on you can execute your procedure simply by calling:
Procedures.RegisterUser();
Another alternative is to introduce a factory pattern to get your objects. This alone won't reduce their number but it might help in getting them all set up already (ie correct connection string).
You also can be creative and combine the two patterns. A custom class implementing IDisposable can take care of creating the necessary ADO objects, open the connection, execute your query, close the connection and dispose of any objects that needs disposal when it is itself disposed of.
Take your pick.
I want to re-use the same SQLConnection accros different methods within the class. What I'm doing right now (testing only) is creating and opening a connection in the constructor:
SQLConnection Connection;
Constructor(string connection_string)
{
this.Connection = new SqlConnection(connection_string);
this.Connection.Open();
}
then I use "this.Connection" inside methods and finally use this.Connection.Close() and Dispose() at the end when the object is not needed anymore. From what I know it would be cleaner to use 'using' inside each method like this (the constructor would only set the connection_string):
using (SqlConnection connection = new SqlConnection(connection_string)) {
connection.Open(); ...
}
Because of connection pooling, only one connection is actually used, despite the above 'using' line being placed in multiple methods (e.g. when they are called one after another), correct? However, wouldn't this create many SQLConnection instances where only one would be needed? E.g.:
MyClass obj(some_string);
obj.Method1(); // calls 'using SqlConnection connection = new SqlConnection'
obj.Method2(); // calls 'using SqlConnection connection = new SqlConnection'
obj.Method3(); // calls 'using SqlConnection connection = new SqlConnection'
So what's the proper, optimal way to share the SQLConnection?
You are correct about all your statements. However you are missing one important point: creating lots of instances of a type in .NET is not necessarily a bad thing!
You should not create a single connection instance in the constructor
You should create a connection locally, when needed
It is best practice to use the using paradigm when creating disposable objects
You should make a habit of calling Dispose on disposable objects in a try...finall block (if not using using) - in case your specific scenario doesn't land itself well for the use of usings; for instance using asynchronous methods)
Finally, you should not keep a SQL connection open for longer than you need it to be. Again, just take advantage of connection pooling in the ADO.NET provider for SQL Server
Now, the reason it's not a problem to create lots of instances of the Connection type is because creating objects in the .NET CLR is optimized (fast memory allocation and object instantiation) and relatively pain free (no need to worry about releasing memory thanks to Garbage Collection).. You also have the benefits of connection pooling in case of the ADO.NET providers so really, you shouldn't concern yourself with managing the number of instances of this Type.
It should be obvious that in other cases (such as heavy/large objects) creating lots of them can have an impact on memory pressure and performance. So always asses the situation as best as you can..
I recently posted (and promptly deleted, when I decided the question was irrelevant to the actual problem) a question about SqlConnection losing its Database information when the scope of "ChangeDatabase" ends. Example:
//Other code...
dbConn = new SqlConnection(dbConnBuilder.ConnectionString);
dbConn.Open();
dbConn.ChangeDatabase(currentDatabase);
dbConn.Close();
}
My questions:
Is it considered bad practice to hold onto a SqlConnection object and open and close it whenever you need it when you'll only ever have ONE connection of a given type?
Why does dbConn.Database not remember currentDatabase after ChangeDatabase (a method not a variable) 'Goes out of scope'? (Heck, I didn't know methods like ChangeDatabase could know about scope).
My connection string was:
Data Source=server.name.com;Persist Security Info=True;User ID=username;Password=password
Thanks guys, let me know if I can give you more information, still learning to use S.O.
Calling Close() completely destroys the object, so you should not be reading any of its properties after.
In fact, there should even be an "after" because you shouldn't be calling Close(). Instead, instantiate the connection in a using block, so that it'll call Dispose(), which does the same thing as Close(), but is guaranteed to do so no matter how you leave the block.
So just make sure to call changedatabase every time you need to execute a statement :-)