我有一个数据访问层命名空间,它有很多重复的代码(主要设置命令对象并执行存储过程以返回添加到列表中的数据集)。我正在尝试编写一个返回List<T>
的通用工厂方法。我对仿制药和代表都比较陌生。我的想法是有一个Func参数,用于创建添加到List<T>
的对象。它将在通常的while dataReader.Read()
块内调用。我的问题是,我将使用的数据集具有不同数量的列。
这是我到目前为止所做的:
private static List<T> ListFromDatabase<T,U>(String CommandName, SqlConnection SqlConn, Func<T,U> CreateListObj,
List<SqlParameter> ParamList = null)
{
List<T> returnList = new List<T>();
using (SqlCommand cmd = new SqlCommand(CommandName,SqlConn))
{
cmd.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter sp in ParamList)
{
if (sp.Value == null)
sp.Value = DBNull.Value;
cmd.Parameters.Add(sp);
}
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
returnList.Add(CreateListObj);
}
}
return returnList;
}
根据我目前的理解水平,这可能是不可能的,因为我可能不得不为不同数量的参数改变Func签名。这可以,还是关闭?如果不是,我会采取不同的方法,如果有人可以提供帮助。非常感谢提前..
更新:这正是我所寻找的:
答案 0 :(得分:1)
执行所需操作的最优雅方法是通过传递接受具有特定数量和类型的项的元组的函数,然后使用Tuple.Create生成该元组,将T指定为Tuple<T1,T2,T3...>
使用sdr中一行的内容。问题是当从DataReader获取字段时,它们作为未确定类型的对象出现,并且当您不知道它们的真实类型是字符串时传递它们的最安全的方式,这意味着CreateListObj函数必须期望字符串和能够正确解析它们(因此期望元组中的特定列顺序)。
答案 1 :(得分:1)
为什么不将SqlDataReader
作为IDataRecord
传递给您的代理人?代表可以从数据记录中获得所需内容;你可以控制迭代阅读器。
答案 2 :(得分:1)
我过去所做的是定义“构建器”方法,它采用IDataReader
并返回它们所定义类型的对象(我将它们作为通用方法类而不是代理,但Func<IDataReader, T>
会做同样的事情。
通常情况下,我在CommandBehavior.CloseConnection
调用中使用了ExecuteReader
,然后返回了一个保留在阅读器上的类,实现了IEnumerable<T>
,然后关闭了阅读器(因此底层当它被处理而不是首先创建一个完整的列表时(如果实际上根本没有枚举枚举器,你必须小心它会被清理)。
优点是我不必担心定义时列数和类型的差异,只是在实现时(我不禁担心它)。