【问题标题】:Does DataAdapter.Fill() close its connection when an Exception is thrown?抛出异常时 DataAdapter.Fill() 是否关闭其连接?
【发布时间】:2011-01-29 04:39:23
【问题描述】:

我在旧版应用程序中使用 ADO.NET (.NET 1.1)。我知道如果在将连接提供给 DataAdapter 之前没有手动打开连接,DataAdapter.Fill() 会打开和关闭连接。

我的问题:如果 .Fill() 导致异常,它是否也会关闭连接?(由于无法访问 SQL Server 或其他原因)。它是否泄漏了一个连接,或者它是否有一个内置的 finally 子句来确保连接被关闭。

代码示例:

Dim cmd As New SqlCommand
Dim da As New SqlDataAdapter
Dim ds As New DataSet
cmd.Connection = New SqlConnection(strConnection)
cmd.CommandText = strSQL
da.SelectCommand = cmd
da.Fill(ds)

【问题讨论】:

  • 在不完全了解的情况下,我会假设它确实如此。但是,您可以使用 Reflector (red-gate.com/products/reflector) 来查看实现,看看它是否最终实现。

标签: .net ado.net .net-1.1 sqlconnection resource-leak


【解决方案1】:

如果在调用 Fill() 方法之前连接是打开的,那么不,连接不会被 DataAdapter 关闭。

但是,如果您没有显式打开连接,而是让 DataAdapter 在 Fill() 命令中打开和关闭连接,则连接将在出错时关闭。

这可以从多个文档来源中得到暗示,包括这个:Data Access Strategies Using ADO.NET and SQL

此外,这可以通过编写一个会出错的例程然后检查连接的状态在代码中进行演示。

来自 Windows 窗体应用程序的这段代码证明了这一点。第一个消息框会显示“打开”,第二个消息框会显示“关闭”。

              string connString = "";
        private void Form1_Load(object sender, EventArgs e)
        {
            connString = Properties.Settings.Default.EventLoggingConnectionString;
            ExplicitlyOpenConnection();
            LetDataAdapterHandleIt();
        }

        private void ExplicitlyOpenConnection()
        {
            System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(connString);
            System.Data.DataSet ds = new DataSet();
            System.Data.SqlClient.SqlDataAdapter ad = new System.Data.SqlClient.SqlDataAdapter("Select bogusdata from nonexistenttable", cn);

            cn.Open();
            try
            {
                ad.Fill(ds);
            }
            catch (Exception ex)
            {

            }

            MessageBox.Show(cn.State.ToString());
            cn.Close();
        }
        private void LetDataAdapterHandleIt()
        {
            System.Data.SqlClient.SqlConnection cn = new System.Data.SqlClient.SqlConnection(connString);
            System.Data.DataSet ds = new DataSet();
            System.Data.SqlClient.SqlDataAdapter ad = new System.Data.SqlClient.SqlDataAdapter("Select bogusdata from nonexistenttable", cn);

            try
            {
                ad.Fill(ds);
            }
            catch (Exception ex)
            {

            }
            MessageBox.Show(cn.State.ToString());
        }

【讨论】:

    【解决方案2】:

    不会关闭连接。此示例有效并输出“ARealTable”的 Id

                using (SqlConnection conn = new SqlConnection("Data Source=server;Initial Catalog=database;user id=sa; password=password;"))
                {
                    conn.Open();
    
                    try
                    {
                        SqlDataAdapter adap = new SqlDataAdapter("SELECT * FROM NotATable", conn); 
                        /* Exception thrown next */
                        adap.Fill(new DataSet("test"));
                    }
                    catch (Exception) { }
    
                    using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 Id FROM ARealTable", conn))
                    {
                        string result = Convert.ToString(cmd.ExecuteScalar());
                        Console.WriteLine(result);
                    }
                    Console.ReadKey();
    

    编辑:

    如果您事先打开连接(在 IDbConnection 对象上调用 Open),IDataAdapter 将不会关闭它。但是,如果您允许 IDataAdapter 完全管理连接,它将被关闭。

    【讨论】:

    • 是的,如果您打开它,您有责任自己关闭它。但是,我正在查看 DataAdapter 为我打开连接的情况。
    • 在这种情况下,它将被DataAdapter关闭。
    • 但是如果您允许数据​​适配器处理关闭,那么插入命令会起作用吗?我同意选择和填充将起作用。
    猜你喜欢
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 2019-01-14
    • 2011-12-10
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多