首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实体框架6-查询性能

实体框架6-查询性能
EN

Stack Overflow用户
提问于 2020-01-21 17:12:04
回答 3查看 532关注 0票数 2

我使用Entity Framework6,目前我有一个包含多个includes的查询,它将大约1200个实体加载到dbContext中。加载实体似乎相当慢,因为查询几乎需要一分钟。关于演出我能做些什么吗?我有4个这样的查询,需要2.5分钟才能加载?LazyLoading已启用,但出于性能原因,我预加载了实体。

代码语言:javascript
复制
var report = DbContext.REPORT.Single(r => r.ID == reportId);

//this query takes a bit less than 1 minute
DbContext.REPORT_ELEMENT
    .Include(re => re.LAYOUT)
    .Include(re => re.PAGEMASTER)
    .Include(re => re.REPORT_ELEMENTS)
    .Include(re => re.SUBTITLE_CONTENT)
    .Include(re => re.REPORT_ELEMENT_NOTE)
    .Include("SUBTITLE_CONTENT.CONTENT_ELEMENT.LANGUAGE")
    .Include("TITLE_CONTENT.CONTENT_ELEMENT.LANGUAGE")
    .Where(re => re.REPORT_ID == report.ID)
    .Load();
EN

回答 3

Stack Overflow用户

发布于 2020-01-21 17:24:07

性能建议:

  • 阻止跟踪。查询处于只读模式。
  • 可防止在一个查询中获取过多数据。请尝试对其进行寻呼。
  • 禁止包含。查询具有太多的Include%s,这会使性能变差。

阻止跟踪

考虑添加AsNoTracking,这样可以更好地提高查询性能。

参考:https://docs.microsoft.com/en-us/ef/core/querying/tracking#no-tracking-queries

只获取您需要的数据

查询慢的关键原因是它输出了太多的数据。考虑添加:Take(200)Skip()以仅获取您需要的数据或当前页面所需的数据。使用分页工具生成报告。这可能会有很大帮助。

防止Include

Include生成用于选择多个表的SQL。这大大增加了复杂性。您只能选择所需的数据,并阻止编写Include函数。

例如,如果你只想得到盒子里的最后一个球,考虑这样写:

代码语言:javascript
复制
public class Box
{
    public int Id { get; set; }
    public IEnumerable<Ball> Balls { get; set; }
}

public class Ball
{
    public int Id { get; set; }

    public int BoxId { get; set; }
    public Box Box { get; set; }
}
代码语言:javascript
复制
var boxes = await Boxes
            // DO NOT Call Include(t => t.Balls) here!
            .Where(somecondition)
            .Select(t => new Box(){
              Id = t.Id,
              Balls = t.Balls.OrderByDescending(x => x.CreationTime)
                         .Take(1) // Only get what you need
            })               
            .ToListAsync()

此外,当我们使用选择时,我们可以删除.Include,因为它在这里不会有任何影响。

票数 1
EN

Stack Overflow用户

发布于 2020-01-21 20:30:41

除了来自Anduin的建议之外,我还想添加一些建议,将Includes()拆分成几个不同的查询。EF将能够跟踪同一DBContext中的实体之间的引用。作为一般经验法则-在同一查询中使用的Includes()不能超过三个。另外,还要确保在数据库中为每个结果连接建立索引。

若要执行此操作,必须将实体中的FK字段另外公开给导航属性。

您的初始查询将如下所示:

代码语言:javascript
复制
    DbContext.LAYOUT
        .Where(re => re.LAYOUT_ID == report.LAYOUT_FK)
        .Load();
    DbContext.PAGEMASTER
        .Where(re => re.PAGEMASTERT_ID == report.PAGEMASTER_FK)
        .Load();
票数 0
EN

Stack Overflow用户

发布于 2020-01-21 21:55:06

免责声明:我是Entity Framework Plus项目的所有者

Query IncludeOptimized特性允许使用include进行过滤,同时优化查询性能。

它通常会提高性能(将查询拆分为较小的查询)

代码语言:javascript
复制
DbContext.REPORT_ELEMENT
    .IncludeOptimized(re => re.LAYOUT)
    .IncludeOptimized(re => re.PAGEMASTER)
    .IncludeOptimized(re => re.REPORT_ELEMENTS)
    .IncludeOptimized(re => re.SUBTITLE_CONTENT)
    .IncludeOptimized(re => re.REPORT_ELEMENT_NOTE)
    .IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT))  // SelectMany?
    .IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT).Select(ce => ce.LANGUAGE)) // SelectMany?
    .IncludeOptimized(re => re.TITLE_CONTENT)
    .IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT)) // SelectMany?
    .IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT).Select(ce => ce.LANGUAGE)) // SelectMany?
    .Where(re => re.REPORT_ID == report.ID)
    .Load();

文档:EF+ Query IncludeOptimized

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59837585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档