Let say i have one asp.net application that is having some page that uses the connection continuesly.....
i have open the connection in class file in construscter ......
and i m accessing it using the object of the class....when ever database operation are required...
in start the application is running fine....but after some operation with database in datagrid(ex. sorting,paging,other).... it's gets slow...and again start working after some time....
do you guys have any solution or any suggession for that.....
i have used the connection in following way....
public class student_operation
{
public SqlConnection cn = new SqlConnection();
public SqlCommand cmd = new SqlCommand();
public SqlDataAdapter ad = new SqlDataAdapter();
public DataSet rs = new DataSet();
public DataSet rs1 = new DataSet();
public student_operation()
{
//
// TODO: Add constructor logic here
//
try
{
cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["myconnection"].ConnectionString);
cn.Open();
}
catch (Exception)
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
cn.Open();
}
}
}
}
Make sure you are opening AND closing your connection. Don't worry about "pooling" the connection. .Net will handle that for you automatically. Just open the connection, do your work and close the connection (even if that's done in the static part).
I don't see where you are closing your connection. I would implement IDisposable and clean everything up there. Then you can access your class in a using statement.
Related
I have an ASP.NET web page. It makes use of 4 BackgroundWorkers. Each bw retrieves some data from a database.
The code for connecting to the database is:
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
DataTable dt = new DataTable();
OdbcCommand cmd = new OdbcCommand(sqlQuery, dbConnection);
cmd.CommandTimeout = 0;
IDataReader dataReader = cmd.ExecuteReader();
dt.Load(dataReader);
dataReader.Close();
dataReader.Dispose();
In the constructor, this.dbConnection = new OdbcConnection(networkdetails);
Each bw makes use of the above code snippet to query the database and retrieve the values. The code works perfectly fine sometimes. Other times it throws the exception given above.
Any help as to what I may be doing wrong?
Try to handle the exception and then close the connection.
For this, write your code in 'Try' block, catch the exception in 'Catch' block and close the connection in 'Finally' block.
try{
// Your code
}
catch
{
// Catch exception
}
Finally
{
// Close the connection
dbConnection.Close();
}
i have created a function which executes query and returns SqlDataReader, now i am using that in another function work with the returned data, but i gets the error saying reader is already closed. here is the functions:
public static SqlDataReader ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
SqlDataReader reader = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
reader = command.ExecuteReader();
}
}
return reader;
}
here is the code where i am calling the SqlDataReader
using (SqlDataReader reader = SqlHelper.ExecuteReader("select top 10 username from users", null, System.Data.CommandType.Text))
{
Response.Write(reader.IsClosed); //This returns True
}
EDIT
ExecuteReader with CommanBehavior ( automatically close connection after reading data)
To over come connection closing proble just make use of CommandBheviour
- CommandBehavior.CloseConnection
When you pass above values as argument to ExecuteReader
1. there is no need to close connection explicitly connection get close when you close your reader.
code will be like this no need to close connection explicitly
public void CreateMySqlDataReader(string mySelectQuery,string myConnectionString)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(mySelectQuery, myConnection);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
while(myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
myReader.Close();
//Implicitly closes the connection because CommandBehavior.CloseConnection was specified.
}
its causing problem because you are closing connection
SqlReader always make use of open connection i.e live connection which is open when you use this
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
it dispose connection object which is used by reader object that why its returing IsColosed as true
If you wanto return value the objec than make use of DataTable which is disconnected data object and doens makse use of connection
Modified code
public static DataTable ExecuteReader(string procedure, SqlParameter[] parameters, CommandType commandType)
{
DataTable dt = null;
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(procedure, connection))
{
connection.Open();
if(parameters != null)
{
if (commandType == CommandType.StoredProcedure)
command.Parameters.AddRange(parameters);
}
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
}
}
return dt;
}
DataReader needs an Open Connection. What you can do it either return a DataTable or Have custom class to represent the results of your SQL query and return an instance of that.
Create a Class to represent your Entity
public class Customer
{
public int ID { set;get;}
public string Name { set;get;}
}
And inside your method;
public List<Customer> GetCustomer()
{
List<Customer> custList=new List<Customer>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("yourParameterizedSQLQuery",
connection))
{
//Add parameters if needed
connection.Open();
using (var reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
cust=new Customer();
while(reader.Read())
{
var cust=new Customer();
// TO DO :Do db null checking before reading
cust.ID=reader.GetInt32(reader.GetOrdinal("ID"));
cust.Name=reader.GetString(reader.GetOrdinal("Name"));
custList.Add(cust);
}
}
}
}
}
return custList;
}
The problem is that you have using SqlConnection which closes the connection to your database when leaving the scope.
SqlDataReader needs a "still open" connection. Returning it to the parent does not keep the connection open.
Your choice are basically to return a DataSet, which is an "unconnected" data source or change the way you manage your connection to open it, use the SqlDataReader, close the connection.
You may have to leave the connection open and let the calling code close the connection associated with the reader.
I had this challenge so I change my return type to DataTable
reader = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
return dt;
That way I don't have to worry about closing the connection outside that method
I am building a web application where a job submitted by user is handled by a background service and the communication between web app and background service is done on database. So when a search starts, web application inserts a record into db and waits till the status field of the record changes. As I understand, if I implement this on the request thread, I am blocking one of the pool threads unnecessarily, but cannot get my head around to do this asynchronously. What is the best practice in this case?
SQLDependency is very useful, but on the server side it provided only half the solution. I overcame the other half by using SignalR to signal the client that the query is over. In the end it was quite an efficient and elegant solution. Thanks for the info!
public class KYHub : Hub
{
void OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= OnChange;
if (e.Info != SqlNotificationInfo.Error && e.Info != SqlNotificationInfo.Delete)
{
string connstr = System.Configuration.ConfigurationManager.ConnectionStrings["cnnStr"].ConnectionString;
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
SearchResult result= SearchResult.Parse(conn, Caller.TaskID);
conn.Close();
Caller.endsearch(result);
}
}
public void Search(SearchParam search)
{
string connstr = System.Configuration.ConfigurationManager.ConnectionStrings["cnnStr"].ConnectionString;
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
search.ClientID = Caller.id;
int QueryID = search.Save(conn);
Caller.TaskID = QueryID;
SqlCommand cmd = new SqlCommand(String.Format("SELECT Completed FROM dbo.Tasks WHERE TaskID={0}", QueryID), conn);
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += OnChange;
cmd.ExecuteReader();
conn.Close();
}
}
If you are using SQL Server as your DB then you can use a ADO.NET feature called SQLDependency,
What this dose when setup correctly is, when ever there is a change in table (which you will configure) a C# event will be raised.
Here is a article that expains it
Note: You will have to setup your SQL server to enable this.
http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
And this one expains how to refresh page after data in table has changed
http://msdn.microsoft.com/en-us/library/e3w8402y%28v=vs.80%29.aspx
i would like to know if there's something wrong in this asp.net code:
mydatareader = mycmd.executeReader()
if myDataReader.HasRow then
// Do something
end if
myConnection.Close()
If i avoid to call a "MyDataReader.Close()" does the connection close anyway ?
I ask this because i'm assuming that if call a "MyConn.Close" it automatically close the associated datareader... or am i wrong ?
Thanks
You have to close your reader instead of closing the connection. Have a look here:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.close.aspx
The best practice to perform such operations is as follows:
using(SqlConnection connection = new SqlConnection(connStr)) {
connection.Open();
SqlCommand command = new SqlCommand(connection, "SELECT...");
SqlDataReader reader = command.ExecuteReader();
// Fill your container objects with data
}
The using statement:
Defines a scope, outside of which an object or objects will be disposed.
So you can be assured that your connection, command and reader variables will be closed and disposed accordingly when exiting the using block.
If you neither close the data reader nor the connection, garbage collector will do it for you. On the other side, this will probably affect the performance of your application.
I'm not absolutely sure but I'm always using try-catch-finally block for db actions:
using (SqlConnection cnn = new SqlConnection(ConnectionString))
{
using (SqlCommand cmmnd = new SqlCommand("SELECT Date();", cnn))
{
try
{
cnn.Open();
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
if (rdr.Read()) { result = rdr[0].ToString(); }
}
}
catch (Exception ex) { LogException(ex); }
finally { cnn.Close(); }
}
}
I have a generic method to call a stored Procedure in ASP.NET:
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlDataReader iReader;
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
iReader = sql.ExecuteReader(CommandBehavior.CloseConnection);
sql.Dispose();
return iReader;
}
Even though I am calling CommandBehavior.CloseConnection the connection is not closing. I can get the data fine the first time I request a page. On reload I get the following error:
The connection was not closed. The
connection's current state is open.
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.
Exception Details:
System.InvalidOperationException: The
connection was not closed. The
connection's current state is open.
Source Error:
Line 35: Line 36: } Line
37: sql.Connection.Open();
Line 38: iReader =
sql.ExecuteReader(CommandBehavior.CloseConnection);
Line 39: sql.Dispose();
Finally if I put sql.Connection.Close(); before sql.Dispose(); I get an error that iReader is not readable because it's been closed already.
Obviously I am closing my connection incorrectly, can someone point me in the right direction?
When you return a DataReader, the underlying connection must remain open. It's the consumer's responsibility to properly clean up resources.
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
return sql.ExecuteReader(CommandBehavior.CloseConnection);
}
public void ConsumingMethod()
{
using(SqlDataReader reader = ExecuteStoredProc("MyProc", params))
{
while(reader.Read())
{
//work with your reader
}
}
}
I would suggest wrap the sql connection with a "using" statement, and that will take care of most sql connection issue.
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
The idea is to do a Connection.Close(); after you've finished with the SqlReader, so basically instead of placing the close() statement before the SqlReader.Dispose() command, you should place it below.
This is my preferred way to process IDataReader. Let the caller creates SqlConnection instance and passes to methods.
It's expensive to create SqlConnection instance. And you’ll end up code call the same ExecuteStoredProc method multiple times in different situation.
Thus, I refactor ExecuteStoredProc method by adding SqlConnection instance as part of the parameter.
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = // Connection String;
conn.Open();
using (IDataReader reader = foo.ExecuteStoredProc(conn, sprocName, SqlP))
{
// Process IDataReader
}
}