我正在创建一个简单的SqlHelper,这将简化ADO.NET方法的使用。有谁能帮我复习一下这门课,看看有没有问题或遗漏了什么?
public static class SqlHelper
{
public static async Task<int> ExecuteNonQueryAsync(string connectionString, CommandType cmdType, string cmdText,
params SqlParameter[] commandParameters)
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(cmdText, connection))
{
try
{
command.CommandType = cmdType;
command.Parameters.AddRange(commandParameters);
connection.Open();
return await command.ExecuteNonQueryAsync();
}
finally
{
connection.Close();
}
}
}
}
public static async Task<SqlDataReader> ExecuteReaderAsync(string connectionString, CommandType cmdType,
string cmdText, params SqlParameter[] commandParameters)
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(cmdText, connection))
{
try
{
command.CommandType = cmdType;
command.Parameters.AddRange(commandParameters);
connection.Open();
return await command.ExecuteReaderAsync();
}
finally
{
connection.Close();
}
}
}
}
public static async Task<object> ExecuteScalarAsync(string connectionString, CommandType cmdType, string cmdText,
params SqlParameter[] commandParameters)
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(cmdText, connection))
{
try
{
command.CommandType = cmdType;
command.Parameters.AddRange(commandParameters);
connection.Open();
return await command.ExecuteScalarAsync();
}
finally
{
connection.Close();
}
}
}
}
}发布于 2014-09-21 18:03:53
可以通过堆叠using块来减少嵌套,如下所示:
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(cmdText, connection))
{
try
{
command.CommandType = cmdType;
command.Parameters.AddRange(commandParameters);
connection.Open();
return await command.ExecuteNonQueryAsync();
}
finally
{
connection.Close();
}
}我喜欢您对var的使用,以及您在using块中包装了IDisposable内容的事实。然而,这是过分的:
finally { connection.Close(); }
因为connection被包装在一个using块中,所以不管代码到达using作用域末尾的原因是什么,连接都将被干净地关闭和释放。换句话说,您还可以丢弃try块,进一步减少嵌套:
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(cmdText, connection))
{
command.CommandType = cmdType;
command.Parameters.AddRange(commandParameters);
connection.Open();
return await command.ExecuteNonQueryAsync();
}这是因为using块是用于.的语言快捷方式。一个try...finally块。
一个名为SqlHelper的静态类的问题是,随着时间的推移,它成为任何与SQL相关的东西的弃置地;它会长头发和触角,甚至在你注意到之前就会变得一团糟:"Helper“这个名字太模糊了,不可能产生任何清晰的焦点。
我建议将它重命名为类似于SqlCommandWrapper的东西,这样它就不太可能因与执行SqlCommand无关的事情而变得臃肿起来,但可能与SqlWhatever有很远的关系。
发布于 2014-09-22 15:35:02
在以前编写了此类类之后,我建议使用以下签名进行额外的重载:
public static async Task<IEnumerable<T>> ExecuteReaderAsync(
string connectionString,
CommandType cmdType,
string cmdText,
Func<IDataReader, T> transform),
params SqlParameter[] commandParameters)使用此重载,您将迭代数据读取器返回的结果,并对每一行调用转换方法并将其存储在List中。完成后,将结果作为IEnumerable返回给调用方。
我的特定实现总是返回一个空的可枚举的,永远不为空的。你可以选择不这样做。(我更喜欢可预测性,并保证该方法永远不会返回null。)
这就避免了调用者不得不自己编写这种样板。他们只是简单地叫:
var foo = await SqlHelper.ExecuteReaderAsync(
myConnectionString,
CommandType.StoredProcedure,
"GetTheFoos",
r => new Foo { Id = r["foo"], Name = r["Name"] },
); // No parameters除此之外,其他评论都很精彩。
发布于 2014-09-21 18:05:02
我不认为必须使用每个命令重复连接字符串更简单。为什么不让SqlHelper成为一个非静态类,将连接字符串传递给构造函数,然后从您的方法中使用它呢?
类似地,我相信大多数命令都将使用CommandType.Text,所以这应该是默认的。不能与params一起使用可选参数,因此必须使用单独的重载。
我不确定ExecuteReaderAsync会不会起作用。返回的读取器不需要打开连接吗?
https://codereview.stackexchange.com/questions/63480
复制相似问题