我有一个Database类,它抽象了SqlCommand的ExecuteNonQuery()和ExecuteReader()。由于使用块包装Sqlconnection和SqlCommand,因此在调用CustomExecuteReader()之后SqlDataReader将关闭,因此我无法在业务级别层读取SqlReaderResultSet。代码如下。谢谢大家的反馈。
public static SqlDataReader SqlReaderResultSet { get; set; }
public static SqlDataReader CustomExecuteReader(string storedProc)
{
using (var conn = new SqlConnection(ConnectionString))
{
var cmd = new SqlCommand(storedProc, conn) {CommandType = CommandType.StoredProcedure};
try
{
conn.Open();
SqlReaderResultSet = cmd.ExecuteReader();
}
catch (InvalidOperationException)
{
if (conn.State.Equals(ConnectionState.Closed))
conn.Open();
}
finally
{
conn.Close();
}
}
return SqlReaderResultSet;
}
答案 0 :(得分:11)
“我无法在业务级别层读取SqlReaderResultSet” - 您不应该这样做。数据应该使用数据传输对象传递,而不是通过低级数据访问结构传递。
答案 1 :(得分:4)
我建议您更改方法,以便上面描述的方法迭代datareader中的记录,并创建对象列表。该对象列表应该返回并处理。
答案 2 :(得分:0)
Iterator Blocks可以解决这个问题。执行以下操作是合法且通常安全的:
IEnumerable<MyFancyData> ResultSet {
get {
using(DbConnection conn = ...)
using(DbCommand cmd = ...) {
conn.Open();
using(DbDataReader reader = cmd.ExecuteReader()) {
while(reader.Read()) {
yield return new MyFancyData(reader[0], reader[42] ...);
}
}
}
}
}
每次枚举ResultSet
属性时,将再次构建连接 - 之后的Disposed(foreach和其他IEnumerator<>
消费者将适当地调用生成器的Dispose()
方法,允许using
块执行其操作。
这种方法保留了对数据阅读器中项目进行评估的懒惰(当数据集变大时可能相关),这仍然可以清除从公共API中抽取sql级别的详细信息。 / p>