我在迭代数据读取器对象时想知道“yield”的连接状态和对代码性能的影响

以下是我用于从数据库获取数据的示例代码:在DAO层上:

public IEnumerable<IDataRecord> GetDATA(ICommonSearchCriteriaDto commonSearchCriteriaDto)
{
    using(DbContext)
    {
        DbDataReader reader = DbContext.GetReader("ABC_PACKAGE.GET_DATA", oracleParams.ToArray(), CommandType.StoredProcedure);
        while (reader.Read())
        {
            yield return reader;
        }
    }
}

在BO层上,我正在调用上面的方法,如:

List<IGridDataDto> GridDataDtos = MapMultiple(_costDriversGraphDao.GetGraphData(commonSearchCriteriaDto)).ToList();

在mapper层上MapMultiple方法定义如下:

public IGridDataDto MapSingle(IDataRecord dataRecord)
{
    return new GridDataDto
    {
        Code = Convert.ToString(dataRecord["Code"]),
        Name = Convert.ToString(dataRecord["Name"]),
        Type = Convert.ToString(dataRecord["Type"])     
    };
}
public IEnumerable<IGridDataDto> MapMultiple(IEnumerable<IDataRecord> dataRecords)
{
    return dataRecords.Select(MapSingle);
}

上面的代码运行良好,但我想知道关于上述代码的两个问题。

  • 数据读取器连接将打开多长时间?
  • 当我仅考虑代码性能因数时,使用“yield return”而不是将记录添加到列表并返回整个列表是否是一个好主意?

  • 您的代码不会显示您打开/关闭连接的位置; 但这里的读者实际上只会在迭代数据时才打开。 延迟执行等。你的代码的唯一一点是.ToList() ,所以它会没事的。 在更一般的情况下,是的:读者将会花费大量的时间来迭代它; 如果你做一个.ToList() ,这将是最小的; 如果你做了一个foreach和(对于每个项目)发出一个外部http请求并等待20秒,那么是的 - 它将会打开更长的时间。
  • 两者都有其用途; 非缓冲方法对于想要作为流处理的巨大结果非常有用,而无需将它们加载到单个内存列表中(或者甚至一次将所有内容加载到内存中); 返回一个列表可以快速关闭连接,并且可以很容易地避免意外地使用连接,但它已经有一个开放的阅读器,但对于大的结果并不理想
  • 如果你返回一个迭代器块,调用者可以决定什么是理智的; 如果你总是返回一个列表,他们没有太多选择。 第三种方法(我们在做的很精巧)是做出选择; 我们有一个可选的bool参数,默认为“返回一个列表”,但调用者可以改变它以指示“返回一个迭代器块”; 基本上:

    bool buffered = true
    

    在参数中,并且:

    var data = QueryInternal<T>(...blah...);
    return buffered ? data.ToList() : data;
    

    在执行中。 在大多数情况下,返回列表是完全合理的,避免了很多问题,因此我们将其作为默认值。


    数据读取器连接将打开多长时间?

    连接将保持开放状态,直到reader被解散,这意味着它将在迭代结束之前一直开放。

    当我仅考虑代码性能因数时,使用yield return而不是将记录添加到列表并返回整个列表是否是一个好主意?

    这取决于几个因素:

  • 如果您不打算获取整个结果, yield return将帮助您节省网络上传输的数据量
  • 如果您不打算将返回的数据转换为对象,或者使用多行来创建单个对象,则yield return将帮助您保存程序高峰使用点处使用的内存
  • 如果您计划在短时间内迭代入门结果集,那么使用yield return将不会有性能损失。 如果迭代要在多个并发线程上持续相当长的时间,RDBMS端的打开游标数可能会超出。

  • 这个答案忽略了所示实现中的缺陷并涵盖了总体思路。

    这是一个折衷 - 在不知道系统约束的情况下不可能判断它是否是一个好主意 - 您希望获得的数据量,您愿意接受的内存消耗,数据库上的预期负载,等等

    链接地址: http://www.djcxy.com/p/53751.html

    上一篇: I am wondering about the state of connection and impact on code performance by 'yield' while iterating over data reader object

    下一篇: Linq to combine (or) join two datatables into one