下面是我使用来从数据库中的数据我的示例代码:对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);
}
上面的代码工作当然好,但我想知道与上面的代码大约两个问题。
- 多久数据读取器的连接会被打开?
- 当我只考虑代码性能的因素,这是使用“收益率的回报”,而不是将记录到一个列表并返回整个列表是一个好主意?
- 代码并不显示在您打开/关闭连接; 但是当你迭代的数据在这里, 读者会实际上只开放。 延期执行,等等,这是否是你的代码的唯一位
.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
会帮你节省你的程序的高峰使用点使用的内存 - 如果您打算迭代enture结果集在很短的时间段,会有使用没有性能损失
yield return
。 如果迭代将要持续的时间对多个并发线程显著量,在RDBMS侧打开的游标的数量可能会变得超出。
这个答案忽略所示实施缺陷和覆盖的总体思路。
这是一个权衡 - 这是不可能告诉它是否是不知道你的系统约束一个好主意 - 是这样的数据,你期望得到的数量,内存消耗,你愿意接受的数据库上,预期负载,等等
文章来源: I am wondering about the state of connection and impact on code performance by 'yield' while iterating over data reader object