Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我想知道';收益率';在数据读取器对象上迭代时_C#_Linq_Using_Datareader_Yield Return - Fatal编程技术网

C# 我想知道';收益率';在数据读取器对象上迭代时

C# 我想知道';收益率';在数据读取器对象上迭代时,c#,linq,using,datareader,yield-return,C#,Linq,Using,Datareader,Yield Return,以下是我用于从数据库获取数据的示例代码: 在DAO层上: public IEnumerable<IDataRecord> GetDATA(ICommonSearchCriteriaDto commonSearchCriteriaDto) { using(DbContext) { DbDataReader reader = DbContext.GetReader("ABC_PACKAGE.GET_DATA", oracleParams.ToArray()

以下是我用于从数据库获取数据的示例代码: 在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;
        }
    }
}
public IEnumerable GetDATA(ICommonSearchCriteriaDto commonSearchCriteriaDto)
{
使用(DbContext)
{
DbDataReader=DbContext.GetReader(“ABC_PACKAGE.GET_DATA”,oracleParams.ToArray(),CommandType.storedProcess);
while(reader.Read())
{
回传阅读器;
}
}
}
在BO层上,我调用上述方法,如下所示:

List<IGridDataDto> GridDataDtos = MapMultiple(_costDriversGraphDao.GetGraphData(commonSearchCriteriaDto)).ToList();
List 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);
}
public-igridatadto-MapSingle(IDataRecord数据记录)
{
返回新的GridDataDto
{
Code=Convert.ToString(dataRecord[“Code”]),
Name=Convert.ToString(数据记录[“Name”]),
Type=Convert.ToString(数据记录[“类型”])
};
}
公共IEnumerable MapMultiple(IEnumerable数据记录)
{
返回数据记录。选择(MapSingle);
}
上面的代码运行良好,但我想知道上面的代码有两个问题

  • 数据读取器的连接将打开多长时间
  • <> LI>当我只考虑代码性能因子时,使用“收益返回”代替将记录添加到列表中并返回整个列表是一个好主意吗?李>
  • 您的代码不显示您在何处打开/关闭连接;但是这里的阅读器实际上只有在您迭代数据时才会打开。延迟执行等。代码中唯一可以执行此操作的部分是
    .ToList()
    ,因此它不会有问题。在更一般的情况下,是的:读者将在您迭代它所花费的时间内打开它;如果您执行
    .ToList()
    操作,则这将是最小的;如果您对每个项目执行一个
    foreach
    ,并发出一个外部http请求并等待20秒,则是-它将打开更长时间
  • 两者都有各自的用途;非缓冲方法非常适合作为流处理的巨大结果,而不必将它们加载到单个内存列表中(甚至一次将所有结果都加载到内存中);返回列表可以使连接快速关闭,并且可以很容易地避免在连接已经有一个打开的读卡器时意外使用该连接,但对于大的结果来说并不理想
  • 如果您返回一个迭代器块,调用方可以决定什么是正常的;如果你总是返回一个列表,他们没有太多选择。第三种方法(我们做得很得体)是让他们做出选择;我们有一个可选的
    bool
    参数,默认为“返回列表”,但调用者可以更改该参数以指示“返回迭代器块”;基本上:

    bool buffered = true
    
    在参数中,以及:

    var data = QueryInternal<T>(...blah...);
    return buffered ? data.ToList() : data;
    
    var数据=查询内部(…废话…);
    返回缓冲?data.ToList():数据;
    
    在执行中。在大多数情况下,返回列表是完全合理的,可以避免很多问题,因此我们将其作为默认值

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

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

    <>当我只考虑代码性能因子时,使用<代码>收益返回<代码>是不是一个好主意,而不是在列表中添加记录并返回整个列表?

    这取决于几个因素:

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

    此答案忽略了所示实现中的缺陷,涵盖了总体思路

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