当我大量使用实现IDisposable的对象时,我使用的是这种模式,如这里所示的SqlConnection和SqlCommand。
private string _connectionString = "";
public IEnumerable<User> GetUsers()
{
List<User> users = new List<User>();
string sql = "SELECT * FROM [user]";
InvokeSql(sql, (connection, command) =>
{
IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
User user = new User();
users.Add(user);
user.Name = reader["name"] as string;
}
});
return users;
}
private void InvokeSql(string sql, Action<SqlConnection, SqlCommand> action)
{
if (string.IsNullOrWhiteSpace(sql))
{
throw new ArgumentNullException("sql");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
using (SqlConnection connection = new SqlConnection(_connectionString))
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
action(connection, command);
}
}因此,我可以重用InvokeSql,而不必费心处理。但是,在使用语句中使用Action真的是个好主意吗?
发布于 2016-04-19 14:30:57
因此,我可以重用InvokeSql,而不必费心处理。
好的。除了InvokeSql是private,所以重用非常局限于该类。如果这个类有一个GetUsers方法,我敢说那个类中只有User-related .而InvokeSql却不是。
很可能,您的模型将不仅仅涉及User实体;我会创建一个基类来封装CRUD和这个InvokeSql方法;然后派生类型可以负责User实体,而另一个派生类型可以负责另一个实体类型--类似于“存储库”。
ExecuteReader返回一个SqlDataReader实例,该实例还实现了IDisposable:这里缺少一个using块:
IDataReader reader = command.ExecuteReader();while (reader.Read())
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
...发布于 2016-04-19 14:49:24
Action<SqlConnection, SqlCommand>对象,则不需要有一个SqlCommand参数。Name列会减缓整个过程。您应该始终只选择所需的列。nameof表达式,比如if (string.IsNullOrWhiteSpace(sql)) {抛出新的ArgumentNullException(nameof(sql));}但是这个抛出的异常不是正确的,因为如果sql只包含空白,则应该抛出ArgumentException。发布于 2016-04-19 15:11:34
不允许委托具有返回类型,这会使自己的生活变得更加艰难。您可以创建接受Func的重载。
private T InvokeSql<T>(string sql, Func<SqlCommand, T> f)
{
// same as before but
return f(command);
}现在,您可以简化:
public IEnumerable<User> GetUsers()
{
string sql = "SELECT * FROM [user]";
return InvokeSql(sql, (command) =>
{
var users = new List<User>();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
users.Add(new User
{
Name = reader["name"] as string
});
}
return users;
});
}不再需要关闭列表,因为可以直接从委托返回列表。
话虽如此,我还是不喜欢API,因为它不清楚如何参数化SQL。另外,任何参数值都必须关闭.
一般来说,我不喜欢让做错事变得容易的APIs -我认为这是一个很好的例子。
https://codereview.stackexchange.com/questions/126113
复制相似问题