7

我正在尝试从 SQL Server 上的 SQL 表中获取 C# 中的列信息。我正在关注此链接中的示例:http: //support.microsoft.com/kb/310107我的程序在尝试关闭连接时奇怪地挂断了。如果连接没有关闭,则程序退出而没有任何异常。这是我的代码:

SqlConnection connection = new SqlConnection(@"MyConnectionString"); 
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
connection.Close(); // Alternatively If this line is commented out, the program runs fast.

SqlConnection内部放入 using 块也会导致应用程序挂起,除非CommandBehavior.KeyInfo将其更改为CommandBehavior.SchemaOnly.

using (SqlConnection connection = new SqlConnection(@"MyConnectionString"))
{
    connection.Open();
    SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
    SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast even here in the using
    DataTable table = reader.GetSchemaTable();
    Console.WriteLine(table.Rows.Count);
}

有问题的表有超过 300 万行,但由于我只获取 Schema 信息,我认为这不是问题。我的问题是:为什么我的应用程序在尝试关闭连接时卡住了?

解决方案:也许这不是最佳的,但它确实有效;我在调用连接command.Cancel();之前插入了一条语句:Close

SqlConnection connection = new SqlConnection(@"MyConnectionString"); 
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo); // If this is changed to CommandBehavior.SchemaOnly, the program runs fast.
DataTable table = reader.GetSchemaTable();
Console.WriteLine(table.Rows.Count);
command.Cancel(); // <-- This is it.
connection.Close(); // Alternatively If this line is commented out, the program runs fast.
4

5 回答 5

7

我很久以前就看到过这样的事情。对我来说,这是因为我做了类似的事情:

SqlCommand command = new SqlCommand("SELECT * FROM MyTable", connection);
SqlDataReader reader = command.ExecuteReader();

// here, I started looping, reading one record at a time
// and after reading, say, 100 records, I'd break out of the loop

connection.Close();  // this would hang

问题是该命令似乎想要完成。也就是说,遍历整个结果集。我的结果集有数百万条记录。它会完成……最终。

command.Cancel()我通过在调用之前添加调用解决了这个问题connection.Close()

有关详细信息,请参阅http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610

于 2012-04-19T01:52:52.683 回答
0

总体而言,它看起来对我来说是正确的,我认为您需要进行一些优化。除了上述关于避免使用 DataReader 的建议外,我还建议使用连接池。您可以从这里获取详细信息:

http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854

于 2012-04-18T21:33:21.233 回答
0

你能试试这个吗?

DataTable dt = new DataTable(); 
using(SqlConnection conn = new SqlConnection("yourConnectionString"))
{
    SqlCommand cmd = new SqlCommand("SET FMTONLY ON; " + yourQueryString + "; SET FMTONLY OFF;",conn);  
    conn.Open(); 
    dt.Load(cmd.ExecuteReader()); 
}

从 MSDN设置 FMTONLY ON/OFF似乎是要走的路

于 2012-04-18T21:48:53.817 回答
0

有一种特定的方法可以做到这一点,使用 SMO(SQL Server 管理对象)

你可以获取数据库中表的集合,然后读取你感兴趣的表的属性(列、键,以及所有可以想象的属性)

这是 SSMS 用来获取和设置所有数据库对象的属性的。

看看这个参考:

这是如何获取表属性的完整示例:

这将允许您以非常简单的方式从数据库中获取所有可能的信息。VB.NET 和 C# 中有大量示例。

于 2012-04-18T22:02:26.643 回答
0

我会尝试这样的事情。这可确保清理所有项目 - 并避免使用 DataReader。除非您有异常大量的数据会导致内存问题,否则您不需要这个。

  public void DoWork(string connectionstring)
    {
        DataTable dt = new DataTable("MyData");
        using (var connection = new SqlConnection(connectionstring))
        {
            connection.Open();
            string commandtext = "SELECT * FROM MyTable";

            using(var adapter = new SqlDataAdapter(commandtext, connection))
            {
                adapter.Fill(dt);
            }
            connection.Close();
        }
        Console.WriteLine(dt.Rows.Count);
    }
于 2012-04-19T00:47:37.217 回答