MySqlConnection really not close - asp.net

i've a huge problem.
Take a look to this sample code
private sub FUNCTION1()
dim conn as new mysqlconnection(myconnstring)
conn.open
---- do something
FUNCTION2()
----
conn.close
end sub
private sub FUNCTION2()
dim conn as new mysqlconnection(myconnstring)
....
conn.open
-- do something
conn.close
end sub
Despite i close regulary all my connection, they remains "open" on the mysql server.
I know this because i'm using MySQL Administration tool to check how many connection i open "line by line" of my source code.
In fact i get a lot of time "user has exceeded the 'max_user_connections' resource (current value: 5)"
My hoster permit ONLY 5 connection, but i think that if i write GOOD source code, this cannot be a problem.
So my question is: why that "damn" connections remain open ??
Thank you in advance!

Consider wrapping your MySqlConnection operations in a Using statement...
Any object that you instantiate within that Using ... new statement will be disposed of properly by the compiler. Once that End Using statement appears, the object goes out of scop. Any objects that are declared with in the Using block will need to be disposed of by the developer, as per normal.
Using conn As New MySqlConnection(myConnString)
Using cmd As New MySqlCommand("SELECT * FROM Employees", conn)
conn.Open()
Using rdr As MySqlDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr(0))
End While
End Using
End Using
End Using
In this case, you don't HAVE to encase your Command and Reader in their own Using, but it allows you to take advantage of the fact that they all implement IDisposable.

Try calling conn.Dispose() and then setting it to null.
On another note, are you opening a connection in Function1 and Function2 also as it appears that you're creating 2 connections. If that's the case try to implement a singleton pattern to manage your connections.

Related

Will this leave a connection open to my database?

I have some legacy code I've inherited and am trying to figure out whether or not this code is causing a connection to stay open to my database. I'm not too familiar with ADO.net but from what I can see this should be causing a problem.
I have a function to get a data reader:
Public Shared Function ExecuteDataReader(ByRef ObjSqlCmd As SqlCommand, ByVal CSTRING As String) As IDataReader
Try
Dim cn As New SqlConnection(CSTRING)
cn.Open()
ObjSqlCmd.Connection = cn
Return ObjSqlCmd.ExecuteReader(CommandBehavior.CloseConnection)
Catch ex As Exception
If ObjSqlCmd.Connection.State = ConnectionState.Open Then ObjSqlCmd.Connection.Close()
Return Nothing
End Try
End Function
And then code using this to read:
Dim cmd As New SqlCommand
'set up command
Dim idr As IDataReader = ExecuteDataReader(cmd, "database")
If idr Is Nothing Then
If cmd.Connection.State = ConnectionState.Open Then cmd.Connection.Close()
Return arrResult
End If
While idr.Read
'read
End While
If cmd.Connection.State = ConnectionState.Open Then cmd.Connection.Close()
I can see it closing the connection at the end (assuming nothing goes wrong and an exception is thrown) but from MSDN they say you should always clsoe the data reader. Does that get closed when the connection is closed?
Also from what I understand, the code
ObjSqlCmd.ExecuteReader(CommandBehavior.CloseConnection)
Will not close the connection unless the data reader is closed. Can someone explain what is happening here and if everything might be closing correctly? I know the best practice is to use "using" and then try/catch/finally to close the reader, the the original developers did not seem to follow these practices.
Yes it will. Any exception that occurs while reading from the data reader will bypass the closing statement. At some point, the garbage collector will kick in and dispose and release the connection back to the connection pool.
Until that point though, the connection can't be used. Worse, any locks acquired while executing the command will remain until the connection is closed.
Using ... using isn't a best practice just because. It's actually a lot simpler and safer to manage commands and connections in this way

Alternatives for SqlCommand.BeginExecuteNonQuery or SQL jobs? (for calling a stored procedure asynchronously from asp.net web page)

Aim: Calling a very slow stored procedure (with parameters) asynchronously from code behind of an asp.net web page via single function call, and then forgetting about it.
Notes: I tried using SqlCommand.BeginExecuteNonQuery without calling SqlCommand.EndExecuteNonQuery (see the code below), but the stored procedure didn't run. (I used a tiny stored procedure to update single field on a table for testing but the field was not updated. It gets update when I use SqlCommand.ExecuteNonQuery).
I am not interested in and don't know when the stored procedure will end. (So I can't wait for it to finish to call SqlCommand.EndExecuteNonQuery.)
Situation:
After some research, I found out that sql jobs can be used for this purpose. And for the sp parameters; I can store them in a table and then sp can read them. However I don't know if this is the right approach to my problem (I am new to SQL world). I hope you can comment on usage of an sql job for this purpose, or suggest alternatives. Thanks.
Code:
using (SqlConnection connection = new SqlConnection(
#"Data Source=XXX\MSSQL2008R2;Initial Catalog=YYY;Integrated Security=True"
+ ";Asynchronous Processing=true"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("spTestProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#pText", DateTime.Now.ToString()));
cmd.BeginExecuteNonQuery(); //Doesn't work.
//cmd.ExecuteNonQuery(); // This works.
}
I think you should simply execute your sp in a separate thread.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Use ThreadPool for example to make a sync call on a separate thread.
It will looks something like this...
Extract method:
private void ExecuteCommandSync()
{
using (SqlConnection connection = new SqlConnection(
#"Data Source=XXX\MSSQL2008R2;Initial Catalog=YYY;Integrated Security=True"
+ ";Asynchronous Processing=true"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("spTestProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#pText", DateTime.Now.ToString()));
cmd.ExecuteNonQuery();
}
}
Change your code:
ThreadPool.QueueUserWorkItem((x) => { ExecuteCommandSync(); });
It will make a synchronous call on some thread from ThreadPool, once it is done - it will close connection and you are done.
It is not the BEST solution performance-wise, because you will have a thread sleeping while it waits for the Stored Proc, but it is good enough and will do what you want.
I was looking for a way of doing this from the code behind of asp.net, but realized there is no easy way of doing it (I didn't want to think about connection or time out problems). I ended up doing it via a web service.
From asp.net code behind, I call my webs service's function synchronously.
Within the web service's function, I call the stored procedure asynchronously using SqlCommand.BeginexecuteNonQuery(AsyncCallback, Object).
The callback is handled within the web service (for error handling).
Hence my web page keeps working the way I want: Fire the request once, then forget about it.

Easy way to run procedure in the background

I'm running stored procedure from asp.net front-end but it's quite long. What is the easy way on running that thing in the background? I mean if I close the browser, I still want my stored procedure to complete not just die. Also, I would like to perform other actions on the front-end while my procedure is running. Any good solution for that?
Both SQL Agent and the Service Broker can do this, though it does take some work on your part.
Just launch it in another Thread as so:
'Starts execution of the proc
Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim t As New Threading.Thread(AddressOf DoWork)
t.Start()
End Sub
Private Sub DoWork()
Using c As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString)
c.Open()
Dim command = New SqlCommand("LongTest", c)
command.CommandType=Data.CommandType.StoredProcedure
command.CommandTimeout = 0
command.ExecuteNonQuery()
End Using
End Sub
Here's the sp that I used for my test:
create PROCEDURE dbo.LongTest
AS
BEGIN
WaitFor Delay '00:00:30' --wait for 30 seconds before doing anything
insert into TableImageTest(image)
values(null)
END
Use "Asynchronous Processing=true" in your connection string and call the sproc asynchronously as in this link.
http://geekswithblogs.net/frankw/archive/2008/07/05/execute-transact-sql-statement-asynchronously.aspx

ODBC Connection in Asp.Net (Connect and Dispose)

I Open and Close ODBC connection while the page is up and running. When and where should i put the Connection.Dispose method? I tried on the Page_Disposed but it never makes it there.
Public Class _WepPage1
Inherits System.Web.UI.Page
Dim MyConnection As New Odbc.OdbcConnection
Private Sub Page_Disposed(sender As Object, e As System.EventArgs) Handles Me.Disposed
MyConnection.Dispose()
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'String comes from Web.Config
MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings("MyConnection").ConnectionString
If Not IsPostBack Then
Call LoadSomeData()
Else
'Do some more stuff
End If
End Sub
Private Sub LoadSomeData()
If MyConnection.State = ConnectionState.Closed Then MyConnection.Open()
Dim MyCommand As New Odbc.OdbcCommand("select * from tablename", MyConnection)
Try
Dim dataR As Odbc.OdbcDataReader = MyCommand.ExecuteReader
While dataR.Read
DropDownList1.Items.Add(dataR("column1"))
End While
Catch ex As Exception
End Try
MyCommand.Dispose()
If MyConnection.State = ConnectionState.Open Then MyConnection.Close()
End Sub
I would not use the Page_Load to start the connection. In .NET, the "real" connection object returns to the pool when you Dispose(), so it is there for other work. Even if you open, close and dispose numerous times, there is but a few microseconds of overhead max, so open a connection early and then keeping it open for the entire page duration does not really help you.
In addition, opening connection in Page_Load means you have tightly coupled your data access to your UI, leaving you a lot of rearchitecture and not just rearrangement to divide the work into proper tiers.
What this means is the connection should be created, used and disposed in one method (in your example). This means it is both logically separated and easy to separate into different classes and/or assemblies, should the application grow so you need a full DAL.
I would, at minimum, move all realting to connection to the LoadSomeData() method. If you want more proper separation of concerns, make a GetSomeData() routine and have the LoadSomeData() routine call the GetSomeData() routine and shape the data so it can be easily bound, rather than consume one row at a time (In your example, instead of binding a data object to the drop down, you are pushing one item at a time).
I hope this helps and I am sorry that many of the examples out there are really bad at best practices. And, yes, this includes many samples from people who should know better. ;-)

ASP.NET logic / connection pooling and error handing

I just uploaded my first ASP.NET (as part of my learning of vb.net) and got into awful mess with the connection pooling (funny things happen when there are more than 1 user of your web site) all sorted now by better use of the try catch statements (well the idea was to learn) BUT I was wondering if this is the best / final method, now if the try fails, then a LOT of the detail on the page isn't placed/updated, so if you are doing some database work and the try fails, do you reload the page ... redirect to self and hope it work the next time ... or just inform the user there was a error and they should try again ?
Thanks
You should defintely use 'using' statements for all objects that implement IDisposable (such as connections and readers). A 'using' statement gets translated into a try-finally block under the covers, and ensures that Dispose() is called even if an error occurs.
Here is a code snippet example:
using (SqlConnection conn = new SqlConnection(this.connectionString))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "LoadFromRepository";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ID", fileID);
conn.Open();
using (SqlDataReader rdr =
cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
while (rdr.Read())
{
// do something with read data
}
}
}
}
If an unexpected error occurs, redirect the user to an error page as it probably will happen the next time around too.
Have you looked into "Using" statements for DB connections and readers?
I would never automatically redirect and hope that it will work the next time (you might get in a infinite loop).
Inform the user and optionally a link to try it again.
You even might want to analyze your exception to see if another try will help. Some exceptions are really bugs, and another try will not help.

Resources