[英]Keeping the SqlDataReader open across an n-tiered layer
I have a Database class that abstracts the ExecuteNonQuery() and ExecuteReader() of SqlCommand. 我有一个Database类,它抽象了SqlCommand的ExecuteNonQuery()和ExecuteReader()。 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.
由于使用块来包装Sqlconnection和SqlCommand,因此在调用CustomExecuteReader()之后SqlDataReader会关闭,因此我无法在业务层读取SqlReaderResultSet。 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;
}
"I can't read the SqlReaderResultSet at the business level layer" - and you shouldn't. “我无法在业务层读取SqlReaderResultSet”-您不应这样做。 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.
该对象列表就是应该返回并处理的对象。
Iterator Blocks can be a way around this. 迭代器块可以解决此问题。 It is legal and generally safe to do the following:
进行以下操作是合法且总体上安全的:
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] ...);
}
}
}
}
}
Each time you enumerate the ResultSet
property, the connection will be constructed again - and Disposed of afterwards (foreach and other IEnumerator<>
consumers will appropriately call the Dispose()
method of the generator, allowing the using
block to do its thing). 每次枚举
ResultSet
属性时,都会重新构造连接-然后进行Dispose()
foreach和其他IEnumerator<>
使用者将适当地调用生成器的Dispose()
方法,从而允许using
块执行其操作)。
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. 这种方法保留了对数据读取器中项目的懒惰按需评估(当您的数据集变大时这可能是相关的),这仍然清除了从公共API提取sql级详细信息的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.