当我发现一个新想法时,我总是坚持下去,看不到它的弱点。当我开始在一个大型项目中使用新想法时,就会发生糟糕的事情,后来发现这个想法非常糟糕,我不应该在任何项目中使用它。
这就是为什么,有一个新想法并准备在一个新的大型项目中使用它,我需要你的意见,尤其是负面的。
很长一段时间,在必须直接访问数据库的项目中,我厌倦了一遍又一遍地键入或复制粘贴以下块:
string connectionString = Settings.RetrieveConnectionString(Database.MainSqlDatabase);
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlCommand getProductQuantities = new SqlCommand("select ProductId, AvailableQuantity from Shop.Product where ShopId = @shopId", sqlConnection))
{
getProductQuantities.Parameters.AddWithValue("@shopId", this.Shop.Id);
using (SqlDataReader dataReader = getProductQuantities.ExecuteReader())
{
while (dataReader.Read())
{
yield return new Tuple<int, int>((int)dataReader["ProductId"], Convert.ToInt32(dataReader["AvailableQuantity"]));
}
}
}
}
所以我做了一个小班,它允许写类似的东西来做和上面一样的事情:
IEnumerable<Tuple<int, int>> quantities = DataAccess<Tuple<int, int>>.ReadManyRows(
"select ProductId, AvailableQuantity from Shop.Product where ShopId = @shopId",
new Dictionary<string, object> { { "@shopId", this.Shop.Id } },
new DataAccess<string>.Yield(
dataReader =>
{
return new Tuple<int, int>(
(int)dataReader["ProductId"],
Convert.ToInt32(dataReader["AvailableQuantity"]);
}));
第二种方法是:
写的更短,
更容易阅读(至少对我来说;有些人可能会说实际上,它的可读性要差得多),
更难出错(例如在第一种情况下,我经常忘记在使用之前打开连接,或者我忘记了
while
阻塞等),在 Intellisense 的帮助下更快,
更加简洁,尤其是对于简单的请求。
例子:
IEnumerable<string> productNames = DataAccess<string>.ReadManyRows(
"select distinct ProductName from Shop.Product",
new DataAccess<string>.Yield(dataReader => { return (string)dataReader["ProductName"]; }));
在一个小项目中用 simple 和 generic 实现了这样的东西后ExecuteNonQuery
,我ExecuteScalar
很高兴看到代码更短且更易于维护。ReadManyRows
DataAccess<T>.ReadManyRows
我发现只有两个缺点:
对需求的一些修改将需要大量的代码更改。例如,如果需要添加事务,用普通的方法很容易做到
SqlCommand
。如果改用我的方法,则需要重写整个项目以使用SqlCommand
s 和事务。命令级别的轻微修改将需要从我的方法转向标准
SqlCommand
s。例如,仅查询一行时,DataAccess
必须扩展任一类以包含这种情况,或者代码必须直接使用SqlCommand
withExecuteReader(CommandBehavior.SingleRow)
代替。可能会有很小的性能损失(我还没有精确的指标)。
这种方法的其他弱点是什么,尤其是对于DataAccess<T>.ReadManyRows
?