保持 SqlDataReader 在 n 层中打开
我有一个数据库类,它抽象了 SqlCommand 的 ExecuteNonQuery() 和 ExecuteReader()。由于使用块包装了 Sqlconnection 和 SqlCommand,SqlDataReader 在调用 CustomExecuteReader() 后关闭,因此我无法在业务级别层读取 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;
}
I have a Database class that abstracts the ExecuteNonQuery() and ExecuteReader() of SqlCommand. Due to wrapping the Sqlconnection and SqlCommand around using blocks, the SqlDataReader gets closed after the CustomExecuteReader() is called, therefore I can't read the SqlReaderResultSet at the business level layer. Code below. Thanks guys for the feedback.
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
“我无法在业务级别读取 SqlReaderResultSet” - 而您不应该这样做。数据应该使用数据传输对象来传递,而不是通过低级数据访问结构。
"I can't read the SqlReaderResultSet at the business level layer" - and you shouldn't. Data should be passed using data transfer objects, never through a low level data access structure.
我建议更改您的方法,以便您上面描述的方法迭代数据读取器中的记录,并创建对象列表。该对象列表是应该返回和处理的对象。
I recommend changing your approach so that the method you describe above iterates the records in the datareader, and creates a list of objects. That list of objects is what should be returned and worked on.
迭代器块可以解决这个问题。执行以下操作是合法且通常安全的:
每次枚举
ResultSet
属性时,都会再次构造连接 - 并随后释放(foreach 和其他IEnumerator
) code> 消费者将适当地调用生成器的Dispose()
方法,从而允许using
块执行其操作)。这种方法保留了对数据读取器中项目的按需评估(当数据集变大时可能相关),这仍然清除了从公共 API 中抽象出 SQL 级详细信息的情况。
Iterator Blocks can be a way around this. It is legal and generally safe to do the following:
Each time you enumerate the
ResultSet
property, the connection will be constructed again - and Disposed of afterwards (foreach and otherIEnumerator<>
consumers will appropriately call theDispose()
method of the generator, allowing theusing
block to do its thing).This approach retains the lazy as-you-need it evaluation of the items from the data reader (which can be relevant when your data set becomes large), which still cleaning abstracting away sql-level details from the public API.