0

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

3 回答 3

11

“我无法在业务级别读取 SqlReaderResultSet” - 你不应该。应该使用数据传输对象传递数据,而不是通过低级数据访问结构。

于 2009-09-16T11:33:50.343 回答
4

我建议更改您的方法,以便您在上面描述的方法迭代数据读取器中的记录,并创建一个对象列表。该对象列表是应该返回和处理的。

于 2009-09-16T11:35:29.560 回答
0

迭代器块可以解决这个问题。执行以下操作是合法且通常安全的:

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属性时,都会再次构造连接 - 并在之后处理(foreach 和其他IEnumerator<>消费者将适当地调用Dispose()生成器的方法,允许using块做它的事情)。

这种方法保留了对来自数据读取器的项目的按需评估的惰性(当您的数据集变大时,这可能是相关的),它仍然从公共 API 中清除抽象的 sql 级细节。

于 2009-09-16T11:55:04.730 回答