Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.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

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# 实体框架/LINQ-从大型嵌套实体数据集中返回数据传输对象_C#_Linq_Entity Framework_Factory_Dto - Fatal编程技术网

C# 实体框架/LINQ-从大型嵌套实体数据集中返回数据传输对象

C# 实体框架/LINQ-从大型嵌套实体数据集中返回数据传输对象,c#,linq,entity-framework,factory,dto,C#,Linq,Entity Framework,Factory,Dto,我正在使用WebAPI和实体框架构建一个RESTAPI,它指向一个大型MSSQL数据库~200个表。数据库非常规范化,因此检索对API使用者有用的值需要深入到表中 为了向消费者返回有用的数据,我采用了使用工厂模式构建模型或DTO的方法。但是,我注意到,尽管所有数据都以一种很好的格式返回,但由于启用了延迟加载,因此存在性能问题。简而言之,我查询了太多的数据,即使我只返回了我需要的数据 因此,我求助于关闭延迟加载,并尝试使用Include方法显式获取数据: var accessions = db.A

我正在使用WebAPI和实体框架构建一个RESTAPI,它指向一个大型MSSQL数据库~200个表。数据库非常规范化,因此检索对API使用者有用的值需要深入到表中

为了向消费者返回有用的数据,我采用了使用工厂模式构建模型或DTO的方法。但是,我注意到,尽管所有数据都以一种很好的格式返回,但由于启用了延迟加载,因此存在性能问题。简而言之,我查询了太多的数据,即使我只返回了我需要的数据

因此,我求助于关闭延迟加载,并尝试使用Include方法显式获取数据:

var accessions = db.AccessionParties
  .Include(ap => ap.Accession.AccessionParties.Select(ap2 => ap2.Party))

  .Include(ap => ap.Accession.AccessionParties.Select(ap2 => ap2.AccessionPartyPurposes.Select  (app => app.PartyAccessionPurposeType)))

  .Include(ap => ap.Accession.AccessionAnimals.Select(x => x.AnimalInformationType))

  .Include(ap => ap.Accession.AccessionAnimals.Select(x => x.Specimens.Select(y => y.AccessionTestRequestSpecimens.Select(z => z.AccessionTestRequest.LabTestOffering.TestOffering))))

  .ToList()
  .Select(a => modelFactory.CreateAccessionModel(a.Accession));
下面是我用来生成模型的工厂方法的一个例子,它包括嵌套的工厂方法以及塑造相关数据实体的方法

  public AccessionModel CreateAccessionModel(Accession accession)
    {
        return new AccessionModel()
        {
            AccessionKey = accession.AccessionKey,
            SubmittedDate = accession.SubmittedDate,
            Parties = accession.AccessionParties
                                .Select(accessionParty => new { accessionParty = accessionParty, accessionParty.Party })
                                .Select(accessionParty => CreatePartyModel(accessionParty.Party)),
            Animals = accession.AccessionAnimals.Select(accessionAnimal => CreateAccessionAnimalModel(accessionAnimal))
        };
    }

是否有处理上述情况的模式或实践?我见过一些方法的例子,它允许您传入一系列include语句,但我想不出一种优雅、高效、实用的方法来处理这个问题。任何意见都将不胜感激

我在我的一个方法中传递了一个字符串数组,这很难看,因为我使用反射来获取属性名,但希望您能理解

private IQueryable<T> AddIncludes<T>(IDatabase db) // my Entity context class implements IDatabase
{
    var props = typeof(IDatabase).GetProperties(BindingFlags.Public|BindingFlags.Instance);
    IQueryable<T> ret = null;
    foreach (var prop in props)
    {
        if (prop.PropertyType.Name == "IDbSet`1" &&
        prop.PropertyType.GetGenericArguments()[0] == typeof(T))
        {
            ret = (IQueryable<T>)prop.GetValue(db, null);
            break;
        }
    }
    var includes = GetIncludes((DbContext)db, typeof(T)); // this returns an IEnumerable<string> of the includes
    foreach (string include in includes) // replace string with a lambda
    {
        ret = ret.Include(include); // this is where the includes are added
    }
    return ret;
}

private ICollection<T> LoadObjectGraph<T>(IDatabase db, Func<T, bool> filter)
{
    var queryableWithIncludesAdded = AddIncludes<T>(db);
    return queryableWithIncludesAdded.Where(filter).ToList();
} 

不使用字符串,您可以使用相同的技术传递lambda来构建查询

您可以使用automapper在实体和DTO之间进行映射,并与投影一起执行查询,只加载DTO需要的列。检查和


希望有帮助

谢谢你,奥马尔。最初我对使用AutoMapper犹豫不决,因为我正在观看一个教程,演示者建议不要在ASP WebAPI项目中使用AutoMapper,因为在我的模型中显示自定义数据时可能会出现一些限制。然而,我现在不知所措,我给了AutoMapper一个机会。和AutoMapper一起去了。到目前为止,它在我需要它做的事情上运行良好。我选择了Omar的答案作为我的回答。Automapper似乎有助于加快进展,我希望这是一个长期的解决方案。非常感谢。