c# - 在 Using 语句中从 DataLayer 返回 DataReader

标签 c# .net database .net-2.0

我们有很多数据层代码都遵循这种非常普遍的模式:

public DataTable GetSomeData(string filter)
{
    string sql = "SELECT * FROM [SomeTable] WHERE SomeColumn= @Filter";

    DataTable result = new DataTable();
    using (SqlConnection cn = new SqlConnection(GetConnectionString()))
    using (SqlCommand cmd = new SqlCommand(sql, cn))
    {
        cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter;

        result.Load(cmd.ExecuteReader());
    }
    return result;
}

我认为我们可以做得更好。我现在的主要提示是它强制将所有记录加载到内存中,即使是大型集合也是如此。我希望能够利用 DataReader 一次只在 ram 中保留一条记录的能力,但如果我直接返回 DataReader,则在离开 using block 时连接会被切断。

我如何改进它以允许一次返回一行?

最佳答案

再一次,我对问题的想法揭示了答案。具体来说,我写的最后一句“一次一行”。我意识到我真的不在乎它是一个数据读取器,只要我可以逐行枚举它即可。这让我想到了这一点:

public IEnumerable<IDataRecord> GetSomeData(string filter)
{
    string sql = "SELECT * FROM [SomeTable] WHERE SomeColumn= @Filter";

    using (SqlConnection cn = new SqlConnection(GetConnectionString()))
    using (SqlCommand cmd = new SqlCommand(sql, cn))
    {
        cmd.Parameters.Add("@Filter", SqlDbType.NVarChar, 255).Value = filter;
        cn.Open();

        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return (IDataRecord)rdr;
            }
        }
    }
}

一旦我们迁移到 3.5 并且可以开始在结果上使用其他 linq 运算符,这将工作得更好,我喜欢它,因为它让我们开始考虑每层之间的“管道”,用于返回的查询很多结果。

缺点是持有多个结果集的读者会很尴尬,但这种情况极为罕见。

更新
自从我在 2009 年开始使用这种模式以来,我了解到最好也将其设为通用 IEnumerable<T>返回类型并添加 Func<IDataRecord, T>参数将 DataReader 状态转换为循环中的业务对象。否则,惰性迭代可能会出现问题,这样您每次都会看到查询中的最后一个对象。

关于c# - 在 Using 语句中从 DataLayer 返回 DataReader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/850065/

相关文章:

c# - Linq 到 SQL 连接

c# - 使用 cmd 或 C# 列出网络上的所有计算机

c# - C#中的多线程应用程序

database - 在数据库列中存储分隔列表真的那么糟糕吗?

c# - 凯撒密码如何同时替换多个字母?

c# - ASP.Net Core MVC UseExceptionHandler 导致空白页面

python - 如何在数据库服务器上运行 South 迁移 (Django)?

mysql - 如果两个条件在子记录的不同行上匹配,则高级 Mysql 查询获取主记录

c# - 为什么空字符串不是连接的标识?

c# - 在 C# 控制台项目中启动一个表单?