when I use using for connections, I know there is no need to use close or dispose. I wonder, do we need to use open?
using (var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"]))
{
dbSqlConnection.Open(); // is this required?
}
Yes, you need to open it.
The using statement calls the Dispose method in a finally block. It doesn't open any connection. If your code inside in using statement doesn't open your connection on behind (like SqlDataAdapter), you need to open it manually.
using (var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"]))
{
}
is equavalent to
var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"];
try
{
}
finally
{
if (dbSqlConnection != null)
((IDisposable)dbSqlConnection).Dispose();
}
As you can see, using statement doesn't do anything about opening a connection.
It depends on what you're doing...if you're manually executing a command using the SqlCommand object you will definitely need to open the connection before you execute any methods on the command. However, if you're using something like DataAdapter...you don't have to because it will manage the connection for you.
Using the SqlCommand object...
using (var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"]))
{
var cmd = new SqlCommand("Your_Sql_Query", con);
dbSqlConnection.Open(); // is this required?
cmd.ExecuteNonQuery();
}
using a SqlDataAdapter...
using (var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"]))
{
DataSet ds = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(
queryString, dbSqlConnection );
adapter.Fill(ds);
}
Notice that the SqlDataAdapter will manage the connection for you, it will open and dispose it
It depends on what you are doing. The SqlAdapter for example opens and closes the connection by itself.
If you use the SqlCommand then yes, you need to open the connection manually to use it
because the constructor of SqlConnection does not open the connection automatically.
As you said, the Dispose method (automatically called when leaving the using block) closes the connection if they is still open.
Using
using (var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"]))
{
dbSqlConnection.Open(); // is this required?
}
Try finally
var dbSqlConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString1"];
try
{
SqlCommand command = new SqlCommand("SELECT ...", dbSqlConnection);
dbSqlConnection.Open();
// execute the SqlCommand e.g. ExecuteReader, ExecuteNonQuery, ExecuteScalar
}
catch (Exception ex)
{
// handle the exception
}
finally
{
// this gets called even if a exception has occured
if (dbSqlConnection != null)
dbSqlConnection.Dispose();
}
MSDN - SqlConnection Class
MSDN - SqlDataAdapter Class
MSDN - SqlCommand Class
MSDN - IDisposable Interface
MSDN - using Statement
no you do not need to do it always its depend on how you going to implement im not use open() command
here is the way to do it automatically with DataAdapter
SqlConnection con = dBClass.SqlConnection(); // return the connection string
SqlDataAdapter da = new SqlDataAdapter("[PR_R_TRN_test]", con);
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.Add("#plong_ID", SqlDbType.BigInt).Value = ID;
DataSet result = new DataSet();
da.Fill(result);
Related
I'm playing around making a POC and I've created the following call.
public string DoStuff()
{
try
{
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
SqlConnection connection = new SqlConnection("Server...");
string command = "insert into Records values (...)";
adapter.InsertCommand = new SqlCommand(command, connection);
}
}
catch (Exception exception)
{
return exception.Message + " " + exception.InnerException;
}
return "WeeHee!";
}
The text I'm seeing returned is the happy one, so I conclude there's no exceptions. Hence, I conclude that the call to the DB is performed as supposed to. However, there's no new lines in the DB being created.
I'm using the same connection string as I have in my config file and the command in pasted in from SQL Manager, where it works.
So my suspicion was that although I create an insert command, I never actually execute it but according to MSDN that's how it's supposed to work.
What stupid thing do I miss here?
You are missing connection.Open(); and adapter.InsertCommand.ExecuteNonQuery();
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
SqlConnection connection = new SqlConnection("Server...");
connection.Open();
string command = "insert into Records values (...)";
adapter.InsertCommand = new SqlCommand(command, connection);
adapter.InsertCommand.ExecuteNonQuery();
}
You should use ExecuteNonQuery instead. Using an SqlDataAdapter for an INSERT query does not make sense.
Also you should Open your connection just before you execute it.
You can:
using(SqlConnection connection = new SqlConnection("Server..."))
{
SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into Records values (...)";
connection.Open();
int craeted = command.ExecuteNonQuery();
}
The example you linked to returned a SQLAdapter for later use.
You don't need one at all:
using (SqlConnection connection = new SqlConnection("Server..."))
{
string command = "insert into Records values (...)";
connection.Open();
var command = new SqlCommand(command, connection);
command.ExecuteNonQuery();
}
Note that there are other execution methods, depending on expected return values and whether you want asynchronous operation: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx
I have the following code behind a button in Visual Studio 2010
private void button1_Click(object sender, EventArgs e)
{
SqlCeConnection Con = new SqlCeConnection();
Con.ConnectionString = "Data Source = 'DB.sdf';" + "Password='my Password';";
SqlCeCommand Query = new SqlCeCommand("SELECT Password FROM Admin");
try
{
Con.Open();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
SqlCeDataReader Reader=Query.ExecuteReader();
MessageBox.Show(Reader["Password"].ToString());
}
It works fine execute and no exception in connection but when I press the button it raises an exception saying
Error: Execute Reader Connection Property Has Not Been Initialized
I'm not going to attempt to comment on database access code in a UI event handler, it will detract from the answer too much. All I will say is, try not to do it.
You haven't associated the connection with the command, either in the command constructor or the relevant Connection property.
I would re-write the entire method to the following to cut out the dangerous try-catch (catching everything, very bad practice) and to utilise the fact using statements also handle object disposal for you:
string password = null;
using (var conn = new SqlCeConnection("Data Source = 'AlviMBRental.sdf'; Password='my Password';"))
using (var comm = new SqlCeCommand("SELECT Password FROM Admin", conn))
{
conn.Open();
using (var reader = comm.ExecuteReader())
{
password = (string)reader["Password"];
} // Dispose reader
// Alternatively, if the resultset is single column and single row, you can do:
var passwordScalar = (string)comm.ExecuteScalar();
} // Dispose command, close / dispose connection.
MessageBox.Show(password ?? "No password found.");
You are not associating your command with your connection - try this:
SqlCeConnection Con = new SqlCeConnection("Data Source = 'AlviMBRental.sdf';Password='my Password';";
SqlCeCommand Query = new SqlCeCommand("SELECT Password FROM Admin", Con); // <== specify "Con" here!
Otherwise, your SqlCeCommand has no connection to work with....
Try like this:
private void button1_Click(object sender, EventArgs e)
{
var connectionString = "Data Source='AlviMBRental.sdf';Password='my Password';";
using (var con = new SqlCeConnection(connectionString))
using (var cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = "SELECT Password FROM Admin";
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
MessageBox.Show(reader["Password"].ToString())
}
}
}
}
Make sure you have associated the connection with the command object. Also make sure you have wrapped IDisposable objects in using statements as shown in my example.
When i debug my application, it gives an error that SelectCommand.Connection Property is not been initialized. i dont know what am i doing here wrong :s. I actually want to add a filter over my search on the textchanged event of a textbox.
public class ConnectionClass
{
static SqlConnection cn;
public static SqlConnection Connection()
{
string myConnection = ConfigurationManager.ConnectionStrings["_uniManagementConnectionString1"].ConnectionString;
if (cn != null)
{
cn = new SqlConnection(myConnection);
cn.Open();
}
return cn;
}
}
public class ClassDataManagement
{
SqlConnection cn = ConnectionClass.Connection();
public DataTable GetData(string SQL)
{
SqlCommand cmd = new SqlCommand(SQL, cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
protected void TextBoxFilterText_TextChanged(object sender, EventArgs e)
{
ClassDataManagement dm = new ClassDataManagement();
string query = "Select CourseCode from _Courses where coursecode like'%" + TextBoxFilterText.Text.TrimEnd() + "%'";
dm.GetData(query);
GridViewCourses.DataBind();
}
That's because your cn variable is null, and not getting initialized. Yet another example why it's a bad idea to initialize and open database connections in a static method.
Try this:
public class ClassDataManagement
{
public DataTable GetData(string SQL)
{
string YourConnectionString = ConfigurationManager.ConnectionStrings["_uniManagementConnectionString1"].ConnectionString;
DataTable dt = new DataTable();
using (SqlConnection cn = new SqlConnection(YourConnectionString))
using (SqlCommand cmd = new SqlCommand(SQL, cn))
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
return dt;
}
}
With the SqlDataAdapter class, you don't need to explicitly call SqlConnection.Open(). The SqlDataAdapter.Fill() method handles all of the connection opening (and closing).
MSDN Reference on SqlDataAdapter.Fill()
As per the above reference, quoted:
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.
Open connection and close as soon as possible.
public DataTable GetData(string commandString)
{
var result = new DataTable();
using (var cn = new SqlConnection(ConfigurationManager.ConnectionStrings["_uniManagementConnectionString1"].ConnectionString))
using (var cmd = new SqlCommand(commandString, cn))
using (var da = new SqlDataAdapter(cmd))
{
da.Fill(result);
}
return result;
}
Shouldn't that be
if (cn == null)
{
cn = new SqlConnection(myConnection);
cn.Open();
}
Although Sebastian's answer covers a good portion of what's wrong. Here is a more complete list.
You have SQL Injection issues. All queries should be parameterized otherwise you are asking for trouble. Especially when you are directly appending text entered by the user.
You are leaking resources: SqlConnection and SqlCommand. These need to be as close to the code that actually utilizes the connection and command as possible. Trust me, Windows is more than capable of handling all of the open/closing of connections through the build in connection pool. You don't need to maintain this yourself.
The code itself is brittle due to use of embedded SQL in your display layer. By way of example, let's say CourseCode is renamed to CourseId. You will have to search through and modify, potentially, a lot of code files just to make that change. There are multiple ways of limiting exposure to this issue; I'll leave that for you to research.
If I ran across this code in the wild, I would delete the ConnectionClass in its entirety. There is nothing that it is going to do for your that shouldn't be done elsewhere in a more robust manner.
Next I would delete the GetData() method. That is just bad code. You should never accept a full sql string and blindly execute it. There are a lot of security issues just in that one block of code.
Then I would rewrite the ClassDataManagement such that my SQL (if I really wanted it to stay embedded, which I wouldn't because I don't roll that way) was the container for all of my queries. I would have good methods like GetCourseByCourseCode(String courseCode) which would validate that the courseCode is in an expected format then pass it to my sqlcommand object as a parameter to the query.
For bonus points I'd expand on the above by looking at what calls could be better served by cached data. By having them in identified methods, it's much easier to pick and choose what can come from the cache vs what I really need to go across the network and run a query for.
Next, I would make sure that everywhere I made a SQL call, I had my SqlConnection, SqlCommand and readers wrapped in using clauses. It's the best way to ensure that everything is properly closed and disposed of prior to leaving the method. Anything less and you are inviting trouble.
Finally, I would highly consider using Enterprise Library for my data access. It's much better.
Having all given advices, to solve your current problem, you may try this way also:
public class ConnectionClass
{
static SqlConnection cn;
public static SqlConnection Connection()
{
string myConnection = ConfigurationManager.ConnectionStrings["_uniManagementConnectionString1"].ConnectionString;
return new SqlConnection(myConnection);
}
}
public class ClassDataManagement
{
public DataTable GetData(string SQL)
{
using (SqlConnection cn = ConnectionClass.Connection())
{
//SqlCommand cmd = new SqlCommand(SQL, cn);
SqlDataAdapter da = new SqlDataAdapter(SQL,cn);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
......
public DataTable GetData()
{
using (System.Data.SqlClient.SqlConnection con = new SqlConnection("YourConnection string"))
{
con.Open();
using (SqlCommand cmd = new SqlCommand())
{
string expression = "Parameter value";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Your Stored Procedure";
cmd.Parameters.Add("Your Parameter Name",
SqlDbType.VarChar).Value = expression;
cmd.Connection = con;
using (SqlDataAdapter da = new SqlDataAdapter(SQL, cn))
{
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
}
}
}
I'm new to asp.net so this might be really basic question, but i cant figure it out.
I found a bit of code on the internet, that connects to database. And i created a namespace and some classes to use the same code in different projects.
The code and my class is the following:
namespace databaseFunctions
{
public class databaseConnection
{
private static string databaseConnectionString()
{
return "DRIVER={MySQL ODBC 5.1 Driver}; ........";
}
public static DataTable getFromDatabase(string SQL)
{
DataTable rt = new DataTable();
DataSet ds = new DataSet();
OdbcDataAdapter da = new OdbcDataAdapter();
OdbcConnection con = new OdbcConnection(databaseConnectionString());
OdbcCommand cmd = new OdbcCommand(SQL, con);
da.SelectCommand = cmd;
da.Fill(ds);
try
{
rt = ds.Tables[0];
}
catch
{
rt = null;
}
return rt;
}
public static Boolean insertIntoDatabase(string SQL)
{
OdbcDataAdapter da = new OdbcDataAdapter();
OdbcConnection con = new OdbcConnection(databaseConnectionString());
OdbcCommand cmd = new OdbcCommand(SQL, con);
con.Open();
try
{
cmd.ExecuteNonQuery();
return true;
}
catch
{
return false;
}
}
}
There is no problem getting data from database, or insert data into some database.
But. when i try to get the last_insert_id() from the mysql database. i only get a zero.
This is why i think that this piece of code I've created and copied from internet, creates a new connection for every time i call the "getFromDatabase(SQL)"
Is there anyone that could help me with fixing this class getFromDatabase() to keep the databaseconnection alive until i tell the program to abandon the connection?
I guess it is the "new OdbcConnection" that should be changed? Is it possible to check if there already is a connection alive?
I've done this hundreds of times in classic asp, but now, with classes and stuff. I'm totally lost.
The problem you face is that you've coded yourself into a "new connection per action" corner. What you really want to aim for,and is considered best practice, is "new connection per batch of actions".
What I recommend in this case is to open connection when required, and close when disposed. What we'll do is move the odbc adapters to a larger scoped variable so that it can be accessed within the class.
namespace databaseFunctions
{
public class databaseConnection:IDisposable
{
private OdbcConnection con;
private string connectionString;
public databaseConnection(string connectionString){
this.connectionString = connectionString;
}
public void OpenConnection(){
if (con == null || con.IsClosed ){ // we make sure we're only opening connection once.
con = new OdbcConnection(this.connectionString);
}
}
public void CloseConnection(){
if (con != null && con.IsOpen){ // I'm making stuff up here
con.Close();
}
}
public DataTable getFromDatabase(string SQL)
{
OpenConnection();
DataTable rt = new DataTable();
DataSet ds = new DataSet();
OdbcCommand cmd = new OdbcCommand(SQL, con);
da.SelectCommand = cmd;
da.Fill(ds);
try
{
rt = ds.Tables[0];
}
catch
{
rt = null;
}
return rt;
}
public Boolean insertIntoDatabase(string SQL)
{
OpenConnection();
OdbcCommand cmd = new OdbcCommand(SQL, con);
con.Open();
try
{
cmd.ExecuteNonQuery();
return true;
}
catch
{
return false;
}
}
// Implementing IDisposable method
public void Dispose(){
CloseConenction();
}
}
}
Now the next time you use your class do something like
using (DatabaseConnection db = new DatabaseConnection()){
db.InsertIntoDatabase(...);
db.GetLastInsertID();
db.GetFromDatabase(...);
}
At the end of that code block, because it is IDisposeable, it will close that connection for you in the dispose method.
Things I changed:
implemented IDisposable interface
changed methods from static to class methods.
added new methods for opening closing connection
moved connection variable to class level scope
added an argument to the constructor that lets you pass in a connection string (you should put this connection string in you Web.Config
Edits:
constructor takes in connectionString per suggestion.
Yes, the code you posted is creating a new database connection every time a method is called, but that's not a problem. The problem is that it is not disposing the connection properly. The way to handle something like this is as follows:
using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
{
con.open();
OdbcCommand command = new OdbcCommand("command_text",con);
command.ExecuteQuery(); //or what ever you need to do
}
That way the connection is being disposed properly since using is just syntactic sugar for try/finally
What you need to do is execute the 2 sql statements in the same transaction in a way that you insert the record in the first sql statement and retrieve the last inserted id on the next insert before ending the transaction. For example:
using (OdbcConnection con = new OdbcConnection("yourconnectionsstring"))
{
con.open();
OdbcTransaction tran = con.BeginTransaction()
OdbcCommand command = new OdbcCommand("first_sql_statement_here",con);
command.ExecuteNonQuery();
command.CommandText = "select last_insert_id();";
int result =command.ExecuteScalar();
tran.commit();
}
That is pretty much the idea.
You should let the connection pool handle your connections; That means you Close() every connection as soon as possible, and only create a new one at the last possible moment.
So yes - keep creating new ones for separate transactions.
I need to run several queries inside one function, will I have to create a new SqlConnection for each? Or having one connection but different SqlCommands works too?
Thanks,
EDIT: Will this work?
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(query1, conn))
{
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = new SqlCommand(query2, conn))
{
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd = new SqlCommand(query3, conn))
{
cmd.ExecuteNonQuery();
}
}
Using the MDSN Documentation as a base:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sql1 = "SELECT ID,FirstName,LastName FROM VP_PERSON";
string sql2 = "SELECT Address,City,State,Code FROM VP_ADDRESS";
using (SqlCommand command = new SqlCommand(sql1,connection))
{
//Command 1
using (SqlDataReader reader = command.ExecuteReader())
{
// reader.Read iteration etc
}
} // command is disposed.
using (SqlCommand command = new SqlCommand(sql2,connection))
{
//Command 1
using (SqlDataReader reader = command.ExecuteReader())
{
// reader.Read iteration etc
}
} // command is disposed.
// If you don't using using on your SqlCommands you need to dispose of them
// by calling command.Dispose(); on the command after you're done.
} // the SqlConnection will be disposed
It doesn't matter which way you go.
SqlConnections are pooled by the operating system. You could literally open and close a connection thousands of times in a row and not incur any performance or other penalty.
How it works is:
Application makes a request to create a db connection (var c = new SqlConnection(...))
The Operating Systems connection pool looks to see if it has a connection sitting idle. If it does, you get a reference to that. If not then it spins up a new one.
Application indicates it is finished with the connection (c.Dispose())
Operating System keeps the connection open for a certain amount of time in case your app, or another one, tries to create another connection to that same resource.
If that connection stays idle until a timeout period passes then the OS finally closes and releases.
This is why the first time you make a connection to a database it might take a second to start before the command(s) can be processed. However if you close it and reopen it then the connection is available immediately. More information is here: http://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx
Now, as to your code, generally speaking you open 1 SqlConnection each time you make a SqlCommand call; however, it is perfectly acceptable/reasonable to make multiple SqlCommand calls while within the same block under the SqlConnection using clause.
Just bear in mind that you do NOT want to keep a SqlConnection object hanging around in your code for any longer than is absolutely necessary. This can lead to a lot of potential issues, especially if you are doing web development. Which means it's far better for your code to open and close 100 SqlConnection objects in rapid succession than it is to hold onto that object and pass it around through various methods.
Having one SqlConnection and many SqlCommands will work fine, however you must make sure that you dispose of any SqlDataReaders that are returned from previous commands before attempting to run additional commands.
using (SqlConnection conn = new SqlConnection())
{
conn.Open()
using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle first resultset here
}
}
using (SqlCommand cmd = new SqlCommand("SELECT otherrow FROM othertable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle second resultset here
}
}
}
Alternaitvely you might be able to combine your commands up into one batch and instead process multiple resultsets, like this:
using (SqlConnection conn = new SqlConnection())
{
conn.Open()
using (SqlCommand cmd = new SqlCommand("SELECT myrow FROM mytable; SELECT otherrow FROM othertable", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle first resultset here, and then when done call
if (reader.NextResult())
{
// Handle second resultset here
}
}
}
}
When you are processing many resultsets you will find that batching together queries like this can significantly improve performance, however it comes at the price of added complexity in your calling code.
Open only one SQLConnection
Use the keyworkd Using as it will automatically dispose the connection.
If you open connection for each one , it can have performance problems.
Example:
using (SqlConnection con = new SqlConnection(connectionString))
{
//
// Open the SqlConnection.
//
con.Open();
//
// The following code shows how you can use an SqlCommand based on the SqlConnection.
//
using (SqlCommand command = new SqlCommand("SELECT TOP 2 * FROM Dogs1", con))
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0} {1} {2}",
reader.GetInt32(0), reader.GetString(1), reader.GetString(2));
}
}
}
One more example:
public DataTable GetData()
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection("your connection here")
{
con.Open();
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "your stored procedure here";
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
Purely as an alternative to the using statements:
SqlConnection con = new SqlConnection(myConnectionString);
SqlCommand cmd = con.CreateCommand();
cmd.CommandText = #"SELECT [stuff] FROM [tableOfStuff]";
con.Open();
SqlDataReader dr = null;
try
{
dr = cmd.ExecuteReader();
while(dr.Read())
{
// Populate your business objects/data tables/whatever
}
}
catch(SomeTypeOfException ex){ /* handle exception */ }
// Manually call Dispose()...
if(con != null) con.Dispose();
if(cmd != null) cmd.Dispose();
if(dr != null) dr.Dispose();
The major difference between this and the using statements, is this will allow you to handle exceptions more cleanly.