保持SqlDataReader在n层的层上打开

时间:2009-09-16 11:31:28

标签: c# sqldatareader

我有一个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;
    }

3 个答案:

答案 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>