我在迭代数据读取器对象时想知道“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);
}
上面的代码运行良好,但我想知道关于上述代码的两个问题。
.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