问题 处理SQL命令并关闭连接


到目前为止,我总是使用类似的结构从DB获取数据并填充DataTable

public static DataTable GetByID(int testID)
        {
        DataTable table = new DataTable();
        string query = @"SELECT * FROM tbl_Test AS T WHERE T.testID = @testID";

        using (SqlConnection cn = new SqlConnection(Configuration.DefaultConnectionString))
        {
            SqlCommand cmd = new SqlCommand(query, cn);
            cmd.Parameters.Add("@testID", SqlDbType.Int).Value = testID;

            cn.Open();
            table.Load(cmd.ExecuteReader());
        }

        return table;
    }

现在我在构建分析中看到了一些警告:

TestService.cs(37):CA2000:Microsoft.Reliability:在方法'TestService.GetByID(int)'中,对象'table'不沿所有异常路径放置。在对对象'table'的所有引用都超出范围之前调用System.IDisposable.Dispose。

TestService.cs(42):CA2000:Microsoft.Reliability:在方法'TestService.GetByID(int)'中,在对所有引用超出范围之前,在对象'cmd'上调用System.IDisposable.Dispose。

我应该更改我的代码吗?

    public static DataTable GetByID(int testID)
    {
        DataTable table = new DataTable();
        string query = @"SELECT * FROM tbl_Test AS T WHERE T.testID = @testID";

        using (SqlConnection cn = new SqlConnection(Configuration.DefaultConnectionString))
        {
            using (SqlCommand cmd = new SqlCommand(query, cn))
            {
                cmd.Parameters.Add("@testID", SqlDbType.Int).Value = testID;

                cn.Open();
                table.Load(cmd.ExecuteReader());
            }
        }

        return table;
    }

如何处理DataTable对象? 将SqlCommand放在使用中是一个好习惯吗?

谢谢

干杯


1824
2017-12-12 14:38


起源

是。你的代码现在是正确的。始终处理实现IDisposable的类。但是SqlDataReader也是一次性的吗? - lnu
您是否处置了返回的DataTable? - Kangkan
我相信读者是一次性的,也许这就是问题WRT表没有处理,因为它拥有一个未明确关闭的读者,尽管我预计它会在处理cmd时隐式关闭。 - Myles McDonnell
你应该这样做:using(SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)){dt.Load(reader); } - lnu
@Kangkan你是什么意思处置DataTable然后返回?我返回那个DataTable,我无法在那里处理它。 - MaiOM


答案:


你也应该这样做:

using (SqlDataReader reader =
            cmd.ExecuteReader
                (CommandBehavior.CloseConnection))
        {
            table.Load(reader);
        }

加载表时


7
2017-12-12 14:47



这是我第一次看到这种方法。为什么在MSDN上甚至没有提到类似的东西? - MaiOM
这是一个选择。 MSDN仅显示样本(简单)案例。而且,是的,你也应该处理数据表。 - lnu
因为我通常是Web应用程序,何时应该调用已使用的DataTable?让我们说在页面加载时我将该方法调用与网格关联并绑定它。在哪里调用处置方法?谢谢 - MaiOM
如果您将它与数据网格或网格视图一起使用,则没有好的方法来处理它,您可以保持原样。只有当你处于另一个环境中时(如果数据表没有直接绑定到控件上),你才可以处理它。此外,似乎(谷歌搜索)虽然它实现了IDisposable,但数据表中没有非托管资源。 - lnu


  • 此方法的调用者应该在使用它时调用返回的DataTable的dispose。
  • 是的,将SqlCommand置于使用中是一个好习惯。

3
2017-12-12 14:43



因为我通常是Web应用程序,何时应该调用已使用的DataTable?让我们说在页面加载时我将该方法调用与网格关联并绑定它。在哪里调用处置方法?谢谢 - MaiOM


要使用DataTable“修复”您的问题,也许您可​​以修改您的功能。

public static void GetByID(DataTable table, int testID)
{
    // bla bla bla
}


// calling the function
using(DataTable table = new DataTable())
{
    TestService.GetByID(table, 5);
}

不是说这是最佳解决方案,但它将解决投诉。


1
2017-12-12 14:46