我正在尝试对我的Sql客户端对象调用进行分层,以使它们得到可靠的处置。像这样:
打开数据库连接->创建命令->读取结果->关闭 命令->关闭数据库连接
到目前为止,当我用相同的方法完成所有这些操作时,这已经成功了。
问题是这容易出错。还有一堆通读。
当我尝试创建一个通用方法来清理所有内容并返回读取器时,连接将在读取器启动之前关闭。
//closes connection before it can be read...apparently the reader doesn't actually have any data at that point ... relocating to disposable class that closes on dispose
public SqlDataReader RunQuery(SqlCommand command)
{
SqlDataReader reader = null;
using (var dbConnection = new SqlConnection(_dbConnectionString))
{
try
{
dbConnection.Open();
command.Connection = dbConnection;
reader = command.ExecuteReader(); // connection closed before data can be read by the calling method
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
dbConnection.Close();
}
}
return reader;
}
我可以通过创建自己的实现IDispose(etc)的类来解决此问题,但是当我用相同的using语句包装它时,它占用的行数与使用statement的数据库连接一样多。
如何在可重复的类中处理数据库连接,该类处理所有这些工件并关闭连接?
答案 0 :(得分:3)
您可以创建一个包含可重用的开放数据库连接的类,但是我建议将数据读入列表并返回结果:
public List<object> RunQuery(SqlCommand command)
{
List<object> results = new List<object>();
using (var dbConnection = new SqlConnection(_dbConnectionString))
{
try
{
dbConnection.Open();
command.Connection = dbConnection;
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// Repeat for however many columns you have
results.Add(reader.GetString(0));
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
return results;
}
我不知道数据的结构,但是重要的一点是,在处置连接之前,您需要读取数据(reader.GetString
是这样做的)。您可以找到有关如何正确读取数据here的更多信息。
编辑:如上所述,我删除了您的finally
语句。这是因为您的using
语句实际上在做同样的事情。您可以将using
语句视为try
-finally
块。退出using
语句后,将始终丢弃您的可丢弃对象。
答案 1 :(得分:1)
因此,没有办法使可重复使用的方法删除所有/大部分嵌套的using语句吗?
有一种支持从方法返回DataReader的特定模式,如下所示:
static IDataReader GetData(string connectionString, string query)
{
var con = new SqlConnection(connectionString);
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = query;
var rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return rdr;
}
然后您可以在using
块中调用此方法:
using (var rdr = GetData(constr, sql))
{
while (rdr.Read())
{
//process rows
}
} // <- the DataReader _and_ the connection will be closed here