I'm just wondering has anybody tried this. It seems so crazy that I need to open a mysql Connection for every call to the database. Sometimes a page requires 3 of 4 calls to the database and it takes extra time to open the connection.
if I create a new Session class and {get;set}; my connection in that class. Is there any harm in this? Theoretically I would this that performance would be increased. Has anybody tried it? And is there any big setbacks?
The MySql Connector/Net supports connection pooling and this is enabled by default.
Typically, you want to close your connection as soon as possible to avoid using up the pool, so storing the connected MySqlConnection in the session would be a bad idea.
You can manage the session without closing on every call by setting it up in the global.asax Session_start Method then closing it in the Sessions_Stop method.
You cannot store a MySqlConnection in a session. It simply isn't possible. The class isn't even serializable so if you used out-of-proc sessions your application would probably explode with an exception.
You can store a reference to a connection in the application domain by using a global class or Global.asax but with pooling this is needless anyhow, you should allow pooling to manage your connections.
Related
I want to use a connection pooling in my C# project. I understand that one I get the connection to the SQL server, while I'm using the same connection string, the cash pooling will work.
However I have doubts about: how is the best practice to pass the connection string through my different classes? Should I pass the connection string as a parameter to the methods that use it to connect? (for instance each time that I need to do a query)
ADO.NET has built-in connection pooling, and you can't really build a better one.
When you create a connection using a connection string, the Framework checks the connection pool to see if a connection with that connection string is available. If one is, it pulls it from the pool and returns it to you; otherwise, it creates a new one and returns that to you.
Similarly, when you close (dispose of) a connection, it is not immediately destroyed.
When you close a connection with a specific connection string, it is not immediately destroyed. Instead, it is released back into the connection pool.
Automatic connection pooling can be disabled, so that you could roll your own solution, but it's not advisable.
EDIT:
As pointed out, I didn't answer the question in my original answer.
In general, you don't pass connection strings around. Instead, they are stored in a configuration file (either web.config or app.config), in the connectionStrings section. When you need a connection string, you retrieve it within the method that requires it using ConfigurationManager.ConnectionStrings.
I'm writing an ASP.NET web application. The database is Oracle. I've recently noticed that if I leave the application open for a while without doing anything and then try to access the database I get "ORA-03135: connection lost contact" error. One reason I can think of first is the connection timeout but I create a fresh new connection, open it, do what I need to do and "finally" close it every time I access the database. What's more interesting is after I get this error, I don't have any problems any more with connecting to the database. Do you have any ideas as to what the problem might be?
Are you using a connection pool?
In this case you can get this behaviour because the Oracle Connection Pool returns a "disconnected" connection. Try adding Validate Connection=True; to your connection string.
I am tracing a bug in a library I did not write myself. When using this library with ASP.NET, I get db connection errors because the SQLConnection seems to get closed when a second Connection is being opened with the same connection string.
Is this documented behaviour? Can opening a new SQLConnection with the same connection string close another SQLConnection object?
From debugging that seems to be the most likely cause for my problems, but I could not find anything on the web to support my theory.
No, what will happen is that when you call the SqlConnection.Open() method, even with the same connection string parameters, it will do one of two things: either reuse an unused connection from the pool, or create a new connection. Either way, you will result in non-conflicting SPIDs for SQL Server.
Is this documented behaviour?
No.
Can opening a new SQLConnection with the same connection string close another SQLConnection object?
No.
Note that unless you've modified the settings, SQL Server permits 32,767 simultaneous connections. But even then, that would not explain the behavior that you are seeing.
In short, opening a new connection with the same connection string will not close your existing connection. However... reusing the already existing object by creating a new reference to a new connection will destroy the connection.
When opening a connection to SQL Server 2005 from our web app, we occasionally see this error:
"Impersonate Session Security Context" cannot be called in this batch because a simultaneous batch has called it.
We use MARS and connection pooling.
The exception originates from the following piece of code:
protected SqlConnection Open()
{
SqlConnection connection = new SqlConnection();
connection.ConnectionString = m_ConnectionString;
if (connection != null)
{
try
{
connection.Open();
if (m_ExecuteAsUserName != null)
{
string sql = Format("EXECUTE AS LOGIN = {0};", m_ExecuteAsUserName);
ExecuteCommand(connection, sql);
}
}
catch (Exception exception)
{
connection.Close();
connection = null;
}
}
return connection;
}
I found an MS Connect article which suggests that the error is caused when a previous command has not yet terminated before the EXECUTE AS LOGIN command is sent. Yet how can this be if the connection has only just been opened?
Could this be something to do with connection pooling interacting strangely with MARS?
UPDATE: For the short-term we have implemented a workaround by clearing out the connection pool whenever this happens, to get rid of the bad connection, as it otherwise keeps getting handed back to various users. (This now happens a 5-10 times a day with only a small number of simultaneous users, so it is fairly annoying.) But if anyone has any further ideas, we are still looking out for a real solution...
I would say it's MARS rather then pooling
From "Using Multiple Active Result Sets (MARS)"
Applications can have multiple default
result sets open and can interleave
reading from them.
Applications can
execute other statements (for example,
INSERT, UPDATE, DELETE, and stored
procedure calls) while default result
sets are open.
Connection pooling in it's basic form means the connection open/close overhead is minimised, but any connection (until MARS) has one thing going on at any one time. Pooling has been around for some time and just works out of the box.
MARS (I've not used it BTW) introduces overlapping "stuff" going on for any single connection. So it's probably MARS rather than connection pooling is the bigger culprit of the 2.
From "Extending Database Impersonation by Using EXECUTE AS"
When impersonating a principal by
using the EXECUTE AS LOGIN statement,
or within a server-scoped module by
using the EXECUTE AS clause, the scope
of the impersonation is server-wide.
This may explain why MARS is causing it: the same principal in 2 session both running EXECUTE AS.
There may be something in that article of use, or try this:
IF ORIGINAL_LOGIN() = SUSER_SNAME() EXECUTE AS LOGIN = {0};
On reflection and after reading for this answer, I've not convinced that trying to change execution context for each session (MARS) in one connections is a good idea...
Don't blame connection pooling - MARS is quite notorious for wreaking a havoc. It's not entirely it's blame but it's kind of half and half. The key thing to remember is that MARS is designed, and only works with "normal" DB use (meaning, regular CRUD stuff no admin batches). Any commands that have a wide effect on DB engine can trip MARS even if it's just one connection and single threaded (like running a setup batch to create tables or a nested transaction).
Having said that, one can easily just blame MARS, but it works perfecly fine for normal CRUD scenarios which are like 99% (and things with low efficiencey like ORM-s and LINQ depend on it for life). Meaning that it's important for people to learn that if they want to hack SQL through a connection they can't use MARS. For example I had a setup code that was creating whole DB from scratch, beceuse it's very convenient for deployment, but it was sharing connection sting with web service it was deploying - oops :-) Took me a few days of digging to learn my lesson. So I just maintain the separation of concerns (which is always good) and problems went away.
Have you tried to use a revert at the end of your sql statement?
http://msdn.microsoft.com/en-us/library/ms178632.aspx
I always do this to just make sure the current context is back to normal.
We have some client code which is using the SqlConnection class in .NET to talk to a SQLServer database. It is intermittently failing with this error:
"ExecuteReader requires an open and available Connection. The connection's current state is Closed"
The "temporary" solution is to reboot the process, after which everything works - however, that's obviously unsatisfactory.
The code is keeping a cache of SqlConnection instances, one for each database.
We'd like to re-write the code, but before I do, I need to know a few things:
My first question is: Is it inefficient to repeatedly connect and disconnect SqlConnection objects, or does the underlying library perform connection pooling on our behalf?
// Is this bad/inefficient?
for(many-times)
{
using(SQLConnection conn = new SQLConnection(connectionString))
{
// do stuff with conn
}
}
Because our code does not do the above, what seems the likely cause of the problem is that something happens to the underlying SQLServer database during the "lifetime" of the connection that causes the connection to be closed...
If it turns out that it is worthwile to "cache" SqlConnection objects, what is the recommended way to handle all errors that could be resolved simply by "reconnecting" to the database. I'm talking about scenarios such as:
The database is taken offline and brought back online, but the client process had no open transactions while this was happening
The database was "disconnected", then "reconnected"
I notice that there is a "State" property on SqlConnection... is there an appropriate way to query that?
Finally, I have a test SQLServer instance set up with full access rights: how can I go about reproducing the exact error "ExecuteReader requires an open and available Connection. The connection's current state is Closed"
No, it's not inefficient to create lots of SqlConnection objects and close each of them when you're done. That's exactly the right thing to do. Let the .NET framework connection pooling do its job - don't try to do it yourself. You don't need to do anything specific to enable connection pooling (although you can disable it by setting Pooling=false in your connection string).
There are many things that could go wrong if you try to cache the connection yourself. Just say no :)
You should enable connection pooling on your connection string. In that case the runtime will add back your connections to the 'pool' when you close them, instead of really disconencting. When a 'new' connection is taken out of the pool it will be reset (ie. sp_reset_connection is called ) then presented to your application as a brand new, fresh connection. The pool is handling transparently such cases as if the connection is closed while idling in the pool.
The cost of creating a new connection 'from scratch' is significant because the authentication requires several roundtrips between client and server (depending on the authentication method and on SSL settings it can be 1 roundtrip in best case vs. about 10 in worse).
And to answer your question, connection raise the OnStateChange event when their state changes, but you shouldn't care about this if you use the pooling.
In my recent experience if you use this code:
using(SQLConnection conn = new SQLConnection(connectionString))
{
// do stuff with conn
}
have an error, and do not explicitly close the connection, it will not be closed or checked back into the pool. So use a catch or finally block to close the connection