C# DataTable and SqlDataAdapter open, close connection and performance issue - c#

This is a function which I used to get data from database
public static DataTable getDataTable(string sql, string tableName)
{
DataTable dt = new DataTable();
try
{
SqlDataAdapter da = new SqlDataAdapter(sql, new SqlConnection(strConn));
da.Fill(dt);
dt.TableName = tableName;
}
catch (Exception)
{
dt = null;
}
return dt;
}
The questions are:
Does it open and close connection automatically? because it seems we only pass the sql query to SqlDataAdapter and it has no open or close the connection.
Does it will cause any performance to slow down the application?
Does it will cause any performance issue the server (Memory)?
Thanks in advance.

i hope this help you
Answer 1 :
If I remember correctly the SQLConnection manages connection pooling behind the scenes.
Here is a nice article about this very subject:
https://msdn.microsoft.com/en-us/library/ms971481.aspx
Also, a best practice is to use the "using" keyword to wrap your connection because it will automatically close your connection once the scope exits (with or without an exception)
using(SqlConnection conn = new SqlConnection())
{
conn.Open();
//Do Work with connection
} //Connection automatically closes here without the need to call conn.Close()
Answer 2:
Sql Connection open slow down or make application performance better
Answer 3 :
What is Best Approach for Opening/Closing SqlConnection in C#

Related

How to solve the "Connection Was Not Closed, The connections current state is open" in c#?

So I'm trying to practice c# and stumbled with the connection error, I already stated that my connection will be closed but it tells me that my connection is still open. I really have no idea what's wrong with this.
public void getdept()
{
con.Open();
string query = "SELECT * FROM positions where PositionName=" + cbxposname.SelectedValue.ToString() + "";
SqlCommand cmd = new SqlCommand(query, con);
DataTable dt = new DataTable();
SqlDataAdapter sda = new SqlDataAdapter(query, con);
sda.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
txtdeptname.Text = dr["Department"].ToString();
}
con.Close();
}
Any tips is welcomed!
You appear to be using a common connection object. Don't. Create your connection object where you use. Do so with a using statement and then the connection will be closed and destroyed at the end of the block. Store your connection string in a common location and then use that each time to create a new connection, e.g.
var table = new DataTable();
using (var connection = new SqlConnection(connectionString)
using (var adapter = new SqlDataAdapter("SQL query here", connection)
{
adapter.Fill(table);
}
// use table here.
There are a number of things to note from this code, other than the using block.
Firstly, it doesn't explicitly open the connection because there's no point. The Fill and Update methods of a data adapter will implicitly open the connection if it's currently closed and it will implicitly close the connection if it opened it. When using a data adapter, the only reason to open the connection explicitly is if you're calling multiple Fill and/or Update methods, so the connection is closed and reopened in between. Even if you do open the connection though, there's still no need to close it explicitly because that happens implicitly at the end of the using block.
Secondly, this code doesn't create a command object because there's no point. In your original code, you create a command object and then you don't use it. If you already have a command object then you can pass that to the data adapter constructor but you don't do that. You pass the SQL query and the connection, so the data adapter will create its own SelectCommand.
In actual fact, there's no point even creating a connection object here. The data adapter has a constructor that accepts a SQL query and a connection string, so you can just create the data adapter and let it do the rest internally:
var table = new DataTable();
using (var adapter = new SqlDataAdapter("SQL query here", connectionString)
{
adapter.Fill(table);
}
// use table here.
You are unnecessary opening and closing connections in your case. It's not needed here.
Your code should look like this.
using (SqlConnection con = new SqlConnection(connetionString))
{
using (DataTable dt = new DataTable())
{
using (SqlDataAdapter sda = new SqlDataAdapter(sql, con))
{
sda.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
txtdeptname.Text = dr["Department"].ToString();
}
}
}
}
A few suggestions also, Please don't use * in the query, instead, use column names, Please use NOLOCK in the Query if it's required in your case and use the parameterized query.

Using MiniProfiler for direct ADO.net calls

This question will be silly for those who are geeks in C# and profilers.
I am new to c# (basically a c++ developer) . I can profile the database queries if it use dbproviderfactory , but i cannot profile the ado.net calls when it is used directly(raw SqlConnection & SqlCommand). I came across the Miniprofiler code where they also profile direct ADO.net calls. I just dont know how to use it ( integrate it in my profiler ).
My code is
SqlConnection myConn = new SqlConnection(#"Server=192.168.23.99;Initial Catalog=cat1;User ID=user21;Password=userpwd");
SqlCommand myCommand = new SqlCommand("select * from table1", myConn);
SqlDataReader dataReader;
System.Threading.Thread.Sleep(5000);
try
{
myConn.Open();
dataReader = myCommand.ExecuteReader();
GridView1.DataSource = dataReader;
GridView1.DataBind();
dataReader.Close();
myCommand.Dispose();
myConn.Close();
}
catch (System.Exception ex)
{
Response.Write(ex.ToString());
}
When the above code gets executed , how will the classes in MiniProfiler will be called? How to make those classes(hope the class name is SimpleProfiledDbCommand) called when my web application calls SqlCommand(..).?
Need a better clarification on this.
According to the documentation, you need to wrap your SqlConnection with the provided ProfiledDbConnection that is able to track your queries:
SqlConnection underlyingConn = new SqlConnection(#"Server=192.168.23.99;Initial Catalog=cat1;User ID=user21;Password=userpwd");
SqlConnection myConn = new StackExchange.Profiling.Data.ProfiledDbConnection(underlyingConn, MiniProfiler.Current);

how to monitor SQL client connection number in C#

In C# client side, we can open SQL connections based on connection string. Connection pool is used to improve the client performance.
We want to monitor how many connections are active and how many are free for use, which is very important to client side health check. Unfortunately, I didn't find any way to get this kind of information. Can any one tell me? Or I have to implement it by myself?
You need to have a wrapper class with count variable to monitor count of connection, on connection.Open() increment by 1 and on connetion.Close() decrement by 1.
public static DataTable GetActiveConnections()
{
DataTable objResult = new DataTable();
try
{
using (SqlConnection conection = new SqlConnection("ConnectionSetting"))
{
conection.Open();
using (SqlCommand cmd = new SqlCommand("sp_who", conection))
{
cmd.CommandType = CommandType.StoredProcedure;
using (SqlDataAdapter adpter = new SqlDataAdapter())
{
adpter.SelectCommand = cmd;
adpter.Fill(objResult);
}
}
}
}
catch (Exception)
{
throw;
}
return objResult;
}
I haven't check it in c# application but i tested it in SQL Server Management Studio

Why does my application hang while trying to close a SqlConnection object?

I am trying to get column information in C# from a SQL table on SQL Server. I am following the example in this link: http://support.microsoft.com/kb/310107 My program strangely gets hung up when it tries to close the connection. If the connection is not closed, the program exits without any Exceptions. Here's my code:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
Putting the SqlConnection inside a using block also causes the application to hang unless CommandBehavior.KeyInfo is changed to CommandBehavior.SchemaOnly.
using (SqlConnection connection = new SqlConnection(#"MyConnectionString"))
{
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast even here in the using
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
}
The table in question has over 3 million rows, but since I am only obtaining the Schema information, I would think this wouldn't be an issue. My question is: Why does my application get stuck while trying to close a connection?
SOLUTION: Maybe this isn't optimal, but it does work; I inserted a command.Cancel(); statement right before Close is called on connection:
SqlConnection connection = new SqlConnection(#"MyConnectionString");
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
command.Cancel(); // <-- This is it.
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
I saw something like this, long ago. For me, it was because I did something like:
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader();
// here, I started looping, reading one record at a time
// and after reading, say, 100 records, I'd break out of the loop
connection.Close(); // this would hang
The problem is that the command appears to want to complete. That is, go through the entire result set. And my result set had millions of records. It would finish ... eventually.
I solved the problem by adding a call to command.Cancel() before calling connection.Close().
See http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610 for more information.
It looks right to me overall and I think you need a little optimization. In addition to the above suggestion regarding avoiding DataReader, I will recommend to use connection pooling. You can get the details from here :
http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854
Could you try this?
DataTable dt = new DataTable();
using(SqlConnection conn = new SqlConnection("yourConnectionString"))
{
SqlCommand cmd = new SqlCommand("SET FMTONLY ON; " + yourQueryString + "; SET FMTONLY OFF;",conn);
conn.Open();
dt.Load(cmd.ExecuteReader());
}
SET FMTONLY ON/OFF from MSDN seems the way to go
There is an specific way to do this, using SMO (SQL Server management objects)
You can get the collection of tables in the database, and then read the properties of the table you're interested in (columns, keys, and all imaginable properties)
This is what SSMS uses to get and set properties of all database objects.
Look at this references:
Database.Tables Property
Table class
This is a full example of how to get table properties:
Retrieving SQL Server 2005 Database Info Using SMO: Database Info, Table Info
This will allow you to get all the possible information from the database in a very easy way. there are plenty of samples in VB.NET and C#.
I would try something like this. This ensures all items are cleaned up - and avoids using DataReader. You don't need this unless you have unusually large amounts of data that would cause memory issues.
public void DoWork(string connectionstring)
{
DataTable dt = new DataTable("MyData");
using (var connection = new SqlConnection(connectionstring))
{
connection.Open();
string commandtext = "SELECT * FROM MyTable";
using(var adapter = new SqlDataAdapter(commandtext, connection))
{
adapter.Fill(dt);
}
connection.Close();
}
Console.WriteLine(dt.Rows.Count);
}

C# - OleDbConnection.Open() causing a crash

Fairly new to C#, anyway, I have this Initialise method that I've written, it basically creates a connection to a MS2007 Access Database, fills a DataSet with the 4 DataTables that are the result of some queries.
public frmDBCompareForm()
{
///
/// Required for Windows Form Design support
///
InitializeComponent();
frmDBCompareForm_Initialize();
//
// TODO: Add any constructor code
//
if (_InstancePtr == null) _InstancePtr = this;
}
And the start of the Initialise Method, including one of the DataTables being filled:
private void frmDBCompareForm_Initialize()
{
// Fill DataSet with 3 DataTables, these tables will be
// made up of the from sQuery.
try
{
// Create a new DataSet
DataSet dsSite1 = new DataSet();
// Set up the connection strings to HCAlias.accdb
OleDbConnection con = new OleDbConnection();
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\HCAlias.accdb;Persist Security Info=False;";
con.Open();
//
// Table 1 - dtSite1Name [cmbSite1]
//
dtSite1Name = new DataTable();
string sQuery = "SELECT SourceName From Sites";
OleDbCommand cmdSite1Name = new OleDbCommand(sQuery, con);
OleDbDataAdapter myDASite1Name = new OleDbDataAdapter(cmdSite1Name);
myDASite1Name.Fill(dsSite1, "dtSite1Name");
cmbSite1.DataSource = dtSite1Name;
cmbSite2.DataSource = dtSite1Name;
Could anyone point me in the right direction for going about this the way I have? Any tips or advice to get that connection issue fixed? I've been Googling like a boss, but can't seem to find the exact issue that I'm having.
You also need to close your connection .
Add also on your finally block with:
using (var con = new OleDbConnection())
{
con.Open();
using (var cmd = new OleDbCommand("sqlquery", conn))
{
try
{
//do Stuff here
}
catch (OleDbException)
{
throw;
}
}
}
regards
This error is caused by leaving connections open. It won't necessarily happen right away but always after the same number of requests.
I suggest wrapping your IDisposable db classes with using statements:
using (OleDbConnection con = new OleDbConnection())
{
}
This will automatically call the implementation on the Dispose() method and close your connections.
From MSDN : "The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler." ... so you do not need your try catch finally

Categories