本文介绍了EF Core嵌套的Linq选择结果在N + 1个SQL查询中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据模型,其中顶部"对象具有0到N个子"对象.在SQL中,这是通过外键dbo.Sub.TopId来实现的.

I have a data model where a 'Top' object has between 0 and N 'Sub' objects. In SQL this is achieved with a foreign key dbo.Sub.TopId.

var query = context.Top
    //.Include(t => t.Sub) Doesn't seem to do anything
    .Select(t => new {
        prop1 = t.C1,
        prop2 = t.Sub.Select(s => new {
            prop21 = s.C3 //C3 is a column in the table 'Sub'
        })
        //.ToArray() results in N + 1 queries
    });
var res = query.ToArray();

在Entity Framework 6中(关闭了延迟加载),此Linq查询将转换为

Issue is tracked on aspnet/EntityFrameworkCore GitHub repo: Issue 4007

更新:EF 2.1版已发布,其中包含一个修复程序.请参阅下面的答案. (2018-05-31)

Update: EF version 2.1 has been released, it includes a fix. see my answer below. (2018-05-31)

推荐答案

GitHub问题#4007 已标记为里程碑2.1.0-preview1closed-fixed.现在,可以在 NuGet .NET博客文章.

The GitHub issue #4007 has been marked as closed-fixed for milestone 2.1.0-preview1. And now the 2.1 preview1 has been made available on NuGet as discussed in this .NET Blog post.

版本2.1正确的版本也已发布,请使用以下命令进行安装:

Version 2.1 proper is also released, install it with the following command:

Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.1.0

然后在嵌套的.Select(x => ...)上使用.ToList()指示应立即获取结果.对于我的原始问题,它看起来像这样:

Then use .ToList() on the nested .Select(x => ...) to indicate the result should be fetched immediately. For my original question this looks like this:

var query = context.Top
    .Select(t => new {
        prop1 = t.C1,
        prop2 = t.Sub.Select(s => new {
            prop21 = s.C3
        })
        .ToList() // <-- Add this
    });
var res = query.ToArray(); // Execute the Linq query

这将导致在数据库上运行2个SQL查询(而不是N + 1);首先是基于Key-ForeignKey关系SELECT FROM'Top'表,然后是SELECT FROM'Sub'表和INNER JOIN FROM'Top'表>.然后将这些查询的结果合并到内存中.

This results in 2 SQL queries being run on the database (instead of N + 1); First a plain SELECT FROM the 'Top' table and then a SELECT FROM the 'Sub' table with an INNER JOIN FROM the 'Top' table, based on Key-ForeignKey relation [Sub].[TopId] = [Top].[Id]. The results of these queries are then combined in memory.

结果正好符合您的期望,并且与EF6所返回的结果非常相似:匿名类型'a的数组,其属性为prop1prop2,其中prop2是匿名类型的列表'b具有属性prop21.最重要的是所有这些都在.ToArray()调用后全部加载!

The result is exactly what you would expect and very similar to what EF6 would have returned: An array of anonymous type 'a which has properties prop1 and prop2 where prop2 is a List of anonymous type 'b which has a property prop21. Most importantly all of this is fully loaded after the .ToArray() call!

这篇关于EF Core嵌套的Linq选择结果在N + 1个SQL查询中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 01:38
查看更多