我寫了下面的代碼(修剪爲簡便起見):我什麼時候必須明確地打開一個SqlConnection?
using (SqlConnection cn = new SqlConnection("Server=test;Database=test;User=test;Password=test"))
using (SqlDataAdapter da = new SqlDataAdapter())
using (DataSet ds = new DataSet())
{
string groupsQuery = @"SELECT GroupName FROM tblGroups ORDER BY GroupName";
da.SelectCommand = new SqlCommand(groupsQuery, cn);
da.Fill(ds);
foreach (System.Data.DataRow row in ds.Tables[0].Rows)
{
string group = row["GroupName"].ToString();
this.GroupList.Add(group);
}
}
我忘了打電話給cn.Open()
,但令我驚訝的是,代碼跑就好了。我懷疑SqlDataAdapter正在做一些魔術,於是我去找了the source。
SqlDataAdapter從DbDataAdapter繼承Fill方法。
填充調用FillInternal,它封裝了邏輯塊,像這樣:
try {
QuietOpen(activeConnection, out originalState);
//... do the fill ...
}
finally {
QuietClose(activeConnection, originalState);
}
QuietOpen
和QuietClose
非常簡單:
static private void QuietClose(IDbConnection connection, ConnectionState originalState) {
// close the connection if:
// * it was closed on first use and adapter has opened it, AND
// * provider's implementation did not ask to keep this connection open
if ((null != connection) && (ConnectionState.Closed == originalState)) {
// we don't have to check the current connection state because
// it is supposed to be safe to call Close multiple times
connection.Close();
}
}
// QuietOpen needs to appear in the try {} finally { QuietClose } block
// otherwise a possibility exists that an exception may be thrown, i.e. ThreadAbortException
// where we would Open the connection and not close it
static private void QuietOpen(IDbConnection connection, out ConnectionState originalState) {
Debug.Assert(null != connection, "QuietOpen: null connection");
originalState = connection.State;
if (ConnectionState.Closed == originalState) {
connection.Open();
}
}
我很好奇,當別人是我在SqlConnection上撥打Open
我不需要需要?我應該總是明確地做,還是讓.NET「靜靜地」做它的事情?
此外,有關SqlDataAdapter爲什麼會這樣做的更多詳細信息的任何引用都會很好。
雖然DataAdapter的工作方式如此,但DataReaders不會。 – LarsTech 2014-11-03 17:06:14