我试图从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
置于使用区块内也会导致应用程序挂起,除非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.
答案 0 :(得分: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。
答案 1 :(得分:0)
总的来说,我认为你需要一点优化。除了上述有关避免DataReader的建议外,我还建议使用连接池。您可以从这里获得详细信息:
http://www.techrepublic.com/article/take-advantage-of-adonet-connection-pooling/6107854
答案 2 :(得分: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的SET FMTONLY ON/OFF似乎要走了
答案 3 :(得分:0)
有一种特定的方法可以做到这一点,使用SMO(SQL Server管理对象)
您可以获取数据库中的表集合,然后读取您感兴趣的表的属性(列,键和所有可以想象的属性)
这是SSMS用于获取和设置所有数据库对象的属性的内容。
看看这个参考文献:
这是如何获取表属性的完整示例:
这将允许您以非常简单的方式从数据库中获取所有可能的信息。 VB.NET和C#中有很多样本。
答案 4 :(得分: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);
}