首页 > 解决方案 > EF Core 3,优化很多 Include/ThenInclude

问题描述

我有这样的查询

return await _ctx.Activities
            .Include(a => a.Attributes)
            .Include(a => a.Roles)
            .Include(a => a.Bookmarks)
            .Include(a => a.VideoMetas)
                .ThenInclude(vm => vm.Instances)
            .Include(a => a.ImageMetas)
                .ThenInclude(im => im.Instances)
            .Include(a => a.Procedure)
                .ThenInclude(p => p.Attributes)
            .FirstOrDefaultAsync(a => a.Id == id);

事实证明这很慢。在EF 6你可以做.Include(v => v.VideoMetas.Select(vm => vm.Instances)的更快一点(我猜,没有看过 SQL Profiler 和实际查询 tbh)。我该如何优化呢?我也可以在它有的地方使用EF Plus.IncludeOptimized()但没有.ThenInclude(). 我听说我可以使用.Select而不是,.Include()但真的不确定如何在这个查询中处理它。

标签: c#sql-serverentity-framework-core

解决方案


您需要将其拆分为多个查询,以提高性能。您可以为此使用显式加载。这不是最漂亮的解决方案,但它有效。希望 EF 5 中会出现更简单的解决方案。

我猜测哪些字段是集合,哪些是“正常”条目,但类似这样:

var activity = await _ctx.Activities.FindAsync(Id);

await context.Entry(activity)
    .Collection(a => a.Attributes)
    .LoadAsync();

await context.Entry(activity)
    .Collection(a => a.Roles)
    .LoadAsync();

await context.Entry(activity)
    .Collection(a => a.Bookmarks)
    .LoadAsync();

await context.Entry(activity)
    .Collection(a => a.VideoMetas)
    .Query()
    .Include(vm => vm.Instances)
    .LoadAsync();

await context.Entry(activity)
    .Collection(a => a.ImageMetas)
    .Query()
    .Include(im => im.Instances)
    .LoadAsync();

await context.Entry(activity)
    .Reference(a => a.Procedure)
    .Query()
    .Include(p => p.Attributes)
    .LoadAsync();

return activity;

推荐阅读