我何时需要显式打开SqlConnection连接?

3
我写了以下代码(为简洁起见进行了修剪):
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 做了一些魔法,于是我找到了源代码

SqlDataAdapter 继承了 Fill 方法从 DbDataAdapter

Fill 调用 FillInternal,并将其逻辑封装在如下的块中:

try {
    QuietOpen(activeConnection, out originalState);

    //... do the fill ...
}
finally {
    QuietClose(activeConnection, originalState);
}

QuietOpenQuietClose非常简单:

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();
    }
}

我很好奇,在什么情况下我会调用Open方法,而我实际上并不需要呢?我应该总是显式地调用它,还是让.NET“悄悄地”做它的事情呢?

此外,如果有关于SqlDataAdapter为什么这样做的更多细节的参考资料,那就太好了。


1
虽然DataAdapters是这样工作的,但DataReaders不会。 - LarsTech
1个回答

2
MSDN上的这个页面中翻译得到:

如果 DataAdapter 发现连接没有打开,则 Fill 方法会隐含地打开所使用的 Connection。 如果 Fill 打开了连接,则在 Fill 完成后,它也会关闭该连接。


但是如果您打开了连接,Fill 不会关闭它?如果您打开了连接,则需要负责关闭它。 - Paul Zahra
@PaulZahra 这是正确的;如果您自己打开了它,Fill() 将不会关闭它。 - Andrew Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接