为什么我的应用程序在尝试关闭 SqlConnection 对象时挂起
本文关键字:SqlConnection 对象 挂起 我的 应用程序 为什么 | 更新日期: 2023-09-27 18:31:46
我正在尝试从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 万行,但由于我只获取架构信息,我认为这不是问题。 我的问题是:为什么我的应用程序在尝试关闭连接时卡住?
解决方案:也许这不是最佳的,但它确实有效;我在连接时调用Close
之前插入了一个 command.Cancel();
语句:
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.
很久以前我看到过这样的东西。对我来说,这是因为我做了这样的事情:
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。
它看起来是正确的,我认为你需要一点优化。除了上述关于避免使用DataReader的建议之外,我建议使用连接池。您可以从这里获取详细信息:
http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854
你能试试这个吗?
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似乎是要走的路
有一种特定的方法可以做到这一点,使用 SMO(SQL Server 管理对象)
您可以获取数据库中的表集合,然后读取您感兴趣的表的属性(列、键和所有可以想象的属性)
这是 SSMS 用于获取和设置所有数据库对象的属性的方法。
看看这个参考资料:
- 数据库.表属性
- 表类
这是如何获取表属性的完整示例:
- 使用 SMO 检索 SQL Server 2005 数据库信息:数据库信息、表信息
这将允许您以非常简单的方式从数据库中获取所有可能的信息。 VB.NET 和 C# 中有很多示例。
我会尝试这样的事情。 这可确保清理所有项目,并避免使用 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);
}