Why does a connection have to be open for a nonquery but not to fill a dataset?

拈花ヽ惹草 提交于 2020-01-15 08:44:05

问题


When I connect to a SQL datasource in my C# application, I can fill a dataset using the following code. Note that I am not explictly opening a connection to the datasource.

SqlConnection cw_con = new SqlConnection("Server=Server;Database=Database;User=User;password=password");
SqlCommand cmd = new SqlCommand("SELECT * FROM Example WHERE value = value");
cmd.Connection = cw_con;

//Create DataSet
DataSet cw_ds = new DataSet("cw_ds");
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
//Execute Command and Fill DataSet
da.Fill(cw_ds);
cw_ds.Clear();

However, If I want to execute a nonquery such as a INSERT INTO or UPDATE why do I have to explicitly open the connection by using connection.Open();?

SqlConnection cw_con = new SqlConnection("Server=Server;Database=Database;User=User;password=password");
cw_con.Open();
SqlCommand cmd = new SqlCommand("UPDATE example SET value = value WHERE value = value");
cmd.Connection = cw_con;
cmd.ExecuteNonQuery();
cw_con.Close();

回答1:


That is because a DataAdapter opens the connection implicitely when it's closed initially. It'll close it afterwards if it was closed before, otherwise the connection stays open.

From MSDN:

The Fill method retrieves the data from the data source using a SELECT statement. The IDbConnection object associated with the select command must be valid, but it does not need to be open. If the IDbConnection is closed before Fill is called, it is opened to retrieve data and then closed. If the connection is open before Fill is called, it remains open.

When using a SqlCommand you must explicitely open and close connections yourself.

As a side note:

  1. Use parameters to avoid SQL-Injection
  2. Use using-statement for anything implementing IDisposable, especially Connections since it ensures that it gets disposed/closed as soon as possible, even in the case of an error



回答2:


From the DataAdapter.Fill documentation

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.

When you use the SqlCommand you're using a lower level class, so you're expected to manage the connection yourself.

Here's a use case where you wouldn't want the connection to automatically be opened because it would be opened and closed several times and its better to simply throw the exception

SqlCommand InsertCmd = new ("Insert statement", cw_con)

cw_con.Open();

foreach (var newitem in collection)
{
   --Set Parameters
   UpdateCmd.ExecuteNonQuery();
}

cw_con.Close();



回答3:


The documentation states that

The Fill method retrieves rows from the data source using the SELECT statement specified by an associated SelectCommand property. 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.

Look here for more information.



来源:https://stackoverflow.com/questions/10620592/why-does-a-connection-have-to-be-open-for-a-nonquery-but-not-to-fill-a-dataset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!