16

这是我用来从数据库中获取数据的示例代码:在 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();

在映射层 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);
}

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

  1. 数据读取器的连接将打开多长时间?
  2. 当我只考虑代码性能因素时,使用'yield return'而不​​是将记录添加到列表中并返回整个列表是个好主意吗?
4

3 回答 3

18
  1. 您的代码未显示您打开/关闭连接的位置;但是这里的阅读器实际上只会在您迭代数据时打开。延迟执行等。您的代码中唯一这样做的是.ToList(),所以它会没事的。在更一般的情况下,是的:阅读器将在您迭代它所花费的时间内保持开放;如果你这样做.ToList(),那将是最小的;如果你做了一个foreach并且(对于每个项目)发出一个外部 http 请求并等待 20 秒,那么是的 - 它会打开更长时间。
  2. 两者都有其用途;非缓冲方法非常适合您想要作为流处理的巨大结果,而无需将它们加载到单个内存列表中(甚至一次将它们全部加载到内存中);返回列表使连接保持快速关闭,并且可以很容易地避免在已经打开阅读器时意外使用连接,但对于大型结果并不理想

如果你返回一个迭代器块,调用者可以决定什么是理智的;如果你总是返回一个列表,他们没有太多选择。第三种方式(我们在 dapper 中所做的)是让他们自己选择;我们有一个可选bool参数,默认为“返回一个列表”,但调用者可以更改它以指示“返回一个迭代器块”;基本上:

bool buffered = true

在参数中,并且:

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

在实施中。在大多数情况下,返回一个列表是完全合理的,并且可以避免很多问题,因此我们将其设为默认值。

于 2013-03-13T09:54:29.180 回答
4

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

连接将保持打开状态,直到reader被解除,这意味着它会一直打开,直到迭代结束。

当我只考虑代码性能因素时,这是一个好主意,yield return而不是将记录添加到列表中并返回整个列表?

这取决于几个因素:

  • 如果您不打算获取整个结果,yield return将帮助您节省在网络上传输的数据量
  • 如果您不打算将返回的数据转换为对象,或者如果使用多行来创建单个对象, yield return将帮助您节省在程序使用高峰时使用的内存
  • 如果您计划在短时间内迭代整个结果集,那么使用yield return. 如果迭代将在多个并发线程上持续很长时间,则可能会超出 RDBMS 端的打开游标数。
于 2013-03-13T09:56:04.767 回答
0

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

这是一个折衷 - 如果不知道系统的限制,就不可能判断这是否是一个好主意 - 您期望获得的数据量是多少,您愿意接受的内存消耗,数据库上的预期负载, ETC

于 2013-03-13T09:56:49.497 回答