SqlDataAdapter Close connection method - c#

I have a code like this in my program and I believe that it's not closing the connection after that the data is getting filled in.
public static string ConnectionInfo = System.Configuration.ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
public static DataTable ExecuteQuery(string query, string table)
{
SqlConnection cnn = new SqlConnection(ConnectionInfo);
SqlDataAdapter Adp = new SqlDataAdapter(query, cnn);
DataSet Ds = new DataSet();
Adp.Fill(Ds, table);
return Ds.Tables[table];
}
Is there any problem in this code ?

The only problem is that you are not using the using statement for the SqlConnection and the DataAdapter. However, DbDataAdapter.Fill opens and closes the connection implicitely.
public static DataTable ExecuteQuery(string query, string table)
{
using(SqlConnection cnn = new SqlConnection(ConnectionInfo))
using(SqlDataAdapter Adp = new SqlDataAdapter(query, cnn))
{
DataTable tbl = new DataTable();
Adp.Fill(tbl);
return tbl;
}
}
The connection object associated with the SELECT statement must be
valid, but it does not need to be open. If the connection is closed
before Fill is called, it is opened to retrieve data, then closed. If
the connection is open before Fill is called, it remains open.
Note that
the using statement will close the connection implicitely even on error
i have used DataAdapter.Fill(DataTable) because you're using a single table anyway
Edit: i've only just noticed that you are using a parameter for the table-name. You can also use DbDataAdapter.Fill(DataSet, String) instead. That does not change anything.

Add a using statement in order to close the connection reliably. This ensures that the connection is closed even if an exception occurs. Change your code as follows:
public static DataTable ExecuteQuery(string query, string table)
{
using(SqlConnection cnn = new SqlConnection(ConnectionInfo))
{
SqlDataAdapter Adp = new SqlDataAdapter(query, cnn);
DataSet Ds = new DataSet();
Adp.Fill(Ds, table);
return Ds.Tables[table];
}
}

Whatever the opening/closing of the connections should be done in try-catch-finally block.
And we should not be using "using"
[using (SqlConnection connection = new SqlConnection(connectionString))]
block. Because if something goes wrong with the network or any exception cause. Connection is not closed. So better to be use try-catch block.
public static DataTable ExecuteQuery(string query, string table)
{
DataSet Ds = new DataSet();
SqlConnection cnn = new SqlConnection(ConnectionInfo);
try{
SqlDataAdapter Adp = new SqlDataAdapter(query, cnn);
Adp.Fill(Ds, table);
return Ds.Tables[table];
}
catch{
throw;
}
finally{
cnn.Close();
}
}

Related

SQLConnection bringing data to TextBox

I know this looks really simple but i've been looking for an answer for hours with no luck.
I want to fill my row values into a bunch of textboxes. How can I specify that [CompanyName] is going to be used by the companyName textbox? Please keep it as simple as possible (beginner level).
string customerUniqueID = "test";
string constr = ConfigurationManager.ConnectionStrings["SQLConnection"].ToString(); // connection string
SqlConnection con = new SqlConnection(constr);
con.Open();
SqlCommand com = new SqlCommand("SELECT * FROM [Customers] WHERE [UniqueID] = #UniqueID", con); // table name
com.Parameters.Add("#UniqueID", SqlDbType.Int);
com.Parameters["#UniqueID"].Value = customerUniqueID;
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
companyName.Text = ?????????
string customerUniqueID = "test";
string constr = ConfigurationManager.ConnectionStrings["SQLConnection"].ToString(); // connection string
SqlConnection con = new SqlConnection(constr);
con.Open();
SqlCommand com = new SqlCommand("SELECT * FROM [Customers] WHERE [UniqueID] = #UniqueID", con); // table name
com.Parameters.Add("#UniqueID", SqlDbType.Int);
com.Parameters["#UniqueID"].Value = customerUniqueID;
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds, "Customers");
companyName.Text = ds.Tables[0].Rows[0]["CompanyName"].ToString();
I will recommend some changes in your code:
Your sql query returning result from one set, so you can use DataTabe instead of DataSet.
To fill results from DB to your DataTable you can use SqlAdapter.Fill() method.
Use Field() generic method (more examples of Field()) to get values from your DataTable.
Use using blocks for disposable objects, or at least make sure you've closed them after.
There is no need of con.Open() to open connection when using Fill() method, because from MSDN:
The Fill method implicitly opens the Connection that the DataAdapter is using if it finds that the connection is not already open. If Fill opened the connection, it will also close the connection when Fill is finished. This can simplify your code when dealing with a single operation such as a Fill or an Update.
string customerUniqueID = "test";
string constr = ConfigurationManager.ConnectionStrings["SQLConnection"].ToString(); // connection string
using(SqlConnection con = new SqlConnection(constr))
{
SqlCommand com = con.CreateCommand();
com.CommandText = "SELECT * FROM [Customers] WHERE [UniqueID] = #UniqueID";
com.Parameters.Add("#UniqueID", SqlDbType.Int);
com.Parameters["#UniqueID"].Value = customerUniqueID;
using(SqlDataAdapter da = new SqlDataAdapter(com))
{
DataTable dt = new DataTable();
da.Fill(dt);
companyName.Text = dt.Rows[0].Field<string>("CompanyName");
}
}
Please feel free to comment, if I missed something.

Code Analysis- Do not dispose objects multiple times

When i analyzed my code from Visual Studio 2013 some warnings appear that "Do not dispose objects multiple times " it also stated that object conn disposed multiple times in object but as i know if i did not use this object multiple times in object than i cant achieve my goals.
so kindly tell me how i can remove this warning ?
here is my code :
private void GetData()
{
DataTable dt = new DataTable();
_connString = ConfigurationManager.AppSettings["connString"];
using (SqlConnection conn = new SqlConnection(_connString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("select * from ref_CourseRegistration_Users", conn);
cmd.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
conn.Close();
if (ds.Tables[0].Rows.Count > 0)
{
grdUsers.DataSource = ds;
grdUsers.DataBind();
}
}
}
here is screenshot of my analysis :
Here if you are using the using statement
using (SqlConnection conn = new SqlConnection(_connString))
no need to close the connection again
so conn.Close(); is not required.
It'll automatically dispose the object.
When you are opening a connection in using block, the using block will automatically call the Dispose() method while leaving the using block scope.
So, conn.Close(); is not required in your code.

How to use variables in all the windows forms?

In my c# project i used many forms and my database is in sql server 2008.
I create one app.config file in that my connection string.
<add name="Courier_Management_System" connectionString="Data Source=.\sqlexpress;Initial Catalog=Courier_Management_System;Integrated Security=True" />
now in all the forms i write the following lines for working with database
SqlConnection cnn = new SqlConnection();
cnn.ConnectionString = ConfigurationManager.ConnectionStrings["Courier_Management_System"].ToString();
SqlDataAdapter adp = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
so my question is if it is possible to write the above all the lines once and use it in all the forms.
Create a class lets say MyDatabase and in its constructor put your code as above and make these variables public. Now you can create object of this class and use these variables, as these will be initialized as soon as you create the object.
Example code:
class MyDatabase
{
SqlConnection cnn;
SqlDataAdapter adp;
DataSet ds;
DataTable dt;
public MyDatabase()
{
cnn = new SqlConnection();
cnn.ConnectionString = ConfigurationManager.ConnectionStrings["Courier_Management_System"].ToString();
adp = new SqlDataAdapter();
ds = new DataSet();
dt = new DataTable();
}
}
Using this class
class YourForm
{
void someMethod()
{
MyDatabase myDatabase = new MyDatabase();
myDatabase.ds = //do something..
gridView.DataSource = myDatabase.ds; //using the variable..
}
}
The right way to do these things is to have a separate project that does the data access. But the most important idea is that you want the data access to take place in one location, e.g. in a class file like Praveen demonstrated. You can even add extra functions to execute queries and return specific resultsets, e.g.:
class MyDatabase
{
SqlConnection cnn;
SqlDataAdapter adp;
DataSet ds;
DataTable dt;
public MyDatabase()
{
cnn = new SqlConnection();
cnn.ConnectionString = ConfigurationManager.ConnectionStrings["Courier_Management_System"].ToString();
adp = new SqlDataAdapter();
ds = new DataSet();
dt = new DataTable();
}
public Dataset ExecuteQuery(string SQL)
{
cnn.Open();
var ret = cnn.Execute(SQL);
cnn.Close();
return ret;
}
}
Create a static method in your Program.cs class
Public Static SqlConnection GetConnection()
{
SqlConnection cnn = new SqlConnection();
cnn.ConnectionString = configurationManager.ConnectionStrings["Courier_Management_System"].ToString();
return cnn;
}
you can call this method as Program.GetConnection() where ever you want a connection object, You only need to change the connection string in only one place if there is any change.
No need to add
SqlDataAdapter adp = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
inside that method , because in most of the time you are not suppose to use those variables .

Returning a Dataset as an Object in a Method

I am writing a method that will query a table and return a Dataset object containing the specified column. Moreover, I have a problem with my Username & Password, so I am using Windows authentication for the same but I am not too sure about that in my snippet I have written till now.
protected void GetProgramList()
{
SqlConnection cn = new SqlConnection("server=Daffodils-PC/sqlexpress;Database=Assignment1;Trusted_Connection=Yes;");
SqlCommand cmd = new SqlCommand("SELECT ProgramName FROM Program", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet1 ds1 = new DataSet1();
}
I have been trying to follow official MS documentation but I am not sure where I am going? Can someone help me with some links or snippets?
I would say you have 2 options here:
1. to make a DataSet class variable, so its reference can be accessed from all over the class (set its access modifier to public so it can be accessed from other classes)
2. or create a method with its return type of DataSet. But in this case on the other side must be set to receive the DataSet as well:
//2. solution:
private void GetData()
{
//from inside some method:
DataSet ds = GetProgramList();
}
protected DataSet GetProgramList()
{
DataSet ds1 = new DataSet();
using (SqlConnection cn = new SqlConnection("server=Daffodils-PC/sqlexpress;Database=Assignment1;Trusted_Connection=Yes;"))
{
using (SqlDataAdapter da = new SqlDataAdapter(#"SELECT ProgramName FROM Program", cn))
da.Fill(ds1, "TableName1");
}
return ds1;
}
//
//1. solution:
class YourClass
{
DataSet ds1;
protected void GetProgramList()
{
SqlConnection cn = new SqlConnection("server=Daffodils-PC/sqlexpress;Database=Assignment1;Trusted_Connection=Yes;");
SqlCommand cmd = new SqlCommand("SELECT ProgramName FROM Program", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
ds1 = new DataSet();
}
}
Place your connection string in AppSettings section in app.config or web.config
public string GetSqlConnection()
{
return System.Configuration.ConfigurationManager.AppSettings["SqlConnectionString"];
}
public DataSet getDataSet(string sql)
{
DataSet ds = new DataSet();
SqlConnection conn = new SqlConnection(GetSqlConnection());
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
da.Fill(ds);
conn.Close();
conn.Dispose();
da.Dispose();
return ds;
}
Suggestion: "use" System.Data and System.Data.SqlClient, and use a "SqlDataReader":
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson04
Either read everything in your routine (generally preferred), or pass the SqlDataReader back to the caller (as a function return).
And be sure to .Close() the reader when you're done :)
SQLDataAdapter basic will get you started with the basics of creating a connection and consuming it in your code.

Trouble loading SQL Data Reader data into DataTable

string query = "select * from cfo_daily_trans_hist";
try
{
using (SqlConnection connection = new SqlConnection(
cnnString))
{
SqlCommand command = new SqlCommand(query);
command.Connection = connection;
connection.Open();
var result = command.ExecuteReader();
DataTable datatable = new DataTable();
datatable.Load(result);
connection.Close();
}
}
So the var result is created through the ExecuteReader(); and HasRows is true, and it shows the correct amount of fields. However, the DataTable that I create from it is empty.
What am I doing wrong? I'm 99% sure it's getting data, but I don't know how to find it through the SqlDataReader object to make sure.
Thanks.
Instead of a SqlDataReader, use a SqlDataAdapter.
SqlDataAdapter myAdapter = new SqlDataAdapter(command);
myAdapter.Fill(datatable);
With a SqlDataAdapter, you don't need to explicitly call SqlConnection.Open() and SqlConnection.Close(). It is handled in the Fill() method.
You can try to add "COALESCE" in your sql command statement ... if you have some NULL value in your query result, you will have problem with dataTable

Categories