【问题标题】:Using Entity Framework Include() multiple times... but separately多次使用实体框架 Include() ......但分开
【发布时间】:2014-10-29 10:53:39
【问题描述】:

所以,我有一个相当大的关系数据库,我正在使用 C#/.Net 中的 EntityFramework 驱动它。我正在尝试对其进行优化,以使其更好地仅获取选定的数据。

在尝试限制任何数据之前,我使用.AsNoTracking() 作为存储库的bool 输入。

到目前为止,我一直在使用所有相关表都包含在查询中的存储库,即使我只想搜索某些内容。

在返回IQueryable<Product> 之前,我基本上得到了大量的.Include(...) 列表。

但是假设我只想返回几个特定的​​表(因为这些是我唯一需要显示某些数据的表),那么最好的方法是什么?

到目前为止,我的存储库为该实体可用的关系接收了一个枚举值列表。

我已经实现了遍历这个列表,并尝试对每个所需的关系执行.Include(...),但这似乎比加载所有内容花费的时间要长得多(有时,甚至超时并给我一个 SQL 超时)。下面是一个简短的 sn-p。

queryIQueryable<Product>

foreach (var part in this.IncludeList)
{
    switch(part)
    {
        case ProductPart.Tag:
        query = query.Include(p => p.Tags);
        break;
        case ProductPart.Video:
        query = query.Include(p => p.Videos);
        break;
    }
}

是否有使用我缺少的链外的诀窍?

【问题讨论】:

  • 是否可以在数据库上跟踪生成的查询?我们最近遇到了一个类似的问题,即 Entity Framework 通过延迟加载获取所有子实体,即使我们使用了 Include。我们可以通过设置 Context.Configuration.LazyLoadingEnabled = false; 来解决这个问题。在此链接中找到:stackoverflow.com/questions/16798796/…
  • @BrunoV 感谢您的评论!不幸的是,我认为这行不通。我已经使用完全相同的代码块this.Context.Configuration.LazyLoadingEnabled = false; 关闭了延迟加载,这可能是我使用return query.AsQueryable(); 造成的,所以我可以使用延迟执行吗?

标签: c# linq entity-framework optimization


【解决方案1】:

请记住 LINQ 使用延迟执行计划。通过您的循环,您期望 EF 创建独立的查询并加载标签,然后是视频。这不会发生。结果查询将等同于:

query = query.Include(p => p.Tags).Include(p => p.Videos);

这可能会导致相当大的 SQL 事务。

如果您想优化您的查询,您应该尝试以下方法:

foreach (var part in this.IncludeList)
{
    switch(part)
    {
        case ProductPart.Tag:
        query.SelectMany(p => p.Tags).Load();
        break;

        case ProductPart.Video:
        query.SelectMany(p => p.Videos).Load();
        break;
    }
}

结果会更高效,因为每个查询都将独立执行,并且导航属性将通过实体框架映射到客户端。

【讨论】:

  • 在多次往返而不是一次往返中获取所有数据将使其花费更长。您在提取相同数量的数据时增加了两次往返的延迟。
  • @Servy :过去,使用这种策略,我能够在 SQL 服务器上将事务大小从 10mb 减少到 500k(根据提琴手)。我会做一些基准测试来确认你说的是对的。
  • 如果是这种情况,那么您所做的更改不仅仅是您在此处描述的转换(或者没有正确测量结果)。在多次往返中加载完全相同的数据不会将加载的数据量减少一个数量级。
  • 重点是:从服务器加载的数据更少。在我的情况下,query 的结果将被加载一次。使用join,每行可能会在结果数据集中重复多次(p.Tag.Count()timesp.Video.Count())也许我错了,我会确认
  • 抱歉,它使用的是 york,而不是 fiddler
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 2016-11-27
  • 2013-09-13
  • 1970-01-01
  • 2022-01-24
相关资源
最近更新 更多