在实体框架核心中的 SelectMany + Select 之后“包含”不起作用

Posted

技术标签:

【中文标题】在实体框架核心中的 SelectMany + Select 之后“包含”不起作用【英文标题】:"Include" not working after SelectMany + Select in Entity Framework Core 【发布时间】:2018-05-11 18:34:45 【问题描述】:

我使用 Entity Framework Core (v2) 进行了此查询,但 Include/ThenInclude 无法按预期工作。这是查询:

 var titlesOwnedByUser = context.Users
                   .Where(u => u.UserId == userId)
                   .SelectMany(u => u.OwnedBooks)
                   .Select(b => b.TitleInformation)
                   .Include(ti => ti.Title)
                   .ThenInclude(n => n.Translations);

查询有效,但我得到的标题设置为null

只是为了澄清类是这些

class User 

     public int Id  get; set; 
     public List<BookUser> OwnedBooks  get; set; 


class Book 

    public int Id  get; set; 
    public TitleInformation TitleInformation  get; set; 
    public List<BookUser> Owners  get; set; 


class BookUser 

     public int BookId  get; set; 
     public int UserId  get; set; 
     public Book Book  get; set; 
     public User User  get; set; 


class MyContext

     protected override void OnModelCreating(ModelBuilder modelBuilder)
     
        modelBuilder.Entity<BookUser>()
            .HasOne(x => x.User)
            .WithMany(x => x.OwnedBooks)
            .HasForeignKey(x => x.UserId);

        modelBuilder.Entity<BookUser>()
            .HasOne(x => x.Book)
            .WithMany(x => x.Owners)
            .HasForeignKey(x => x.BookId);
     


class TitleInformation

    public int Id  get; set; 
    public Title Title  get; set; 
    public Title Subtitle  get; set; 


class Title

     public int Id  get; set; 
     public string OriginalTitle  get; set; 
     public List<Translation> Translations  get; set; 

我必须做些什么才能使返回的可查询的翻译加载?

【问题讨论】:

你能显示实体的配置吗? 听起来像Ignored includes。您应该以其他方式构建查询,从 context.TitleInformation 开始。 @H.Herzl 请检查更新 OP。 @IvanStoev 我怎么知道如何开始?你能包括代码吗?我有点失落:( Entity Framework Core SelectMany then Include的可能重复 【参考方案1】:

这是Loading Related Data - Ignored includes 中描述的当前 EF Core 限制:

如果您更改查询以使其不再返回查询开始时使用的实体类型的实例,则包含运算符将被忽略。

据此,您需要从context.Set&lt;TitleInformation&gt;() 开始查询。但为了产生所需的过滤,您需要从 TitleInformationBook 的反向导航属性,目前您的模型中缺少该属性:

class TitleInformation

    // ...
    public Book Book  get; set;  // add this and map it properly with fluent API

一旦你有了它,你就可以使用这样的东西:

var titlesOwnedByUser = context.Set<TitleInformation>()
    .Include(ti => ti.Title)
        .ThenInclude(n => n.Translations)
    .Where(ti => ti.Book.Owners.Any(bu => bu.UserId == userId));

或者,如果TitleInformationBook之间的关系是一对多(以上是一对一):

class TitleInformation

    // ...
    public List<Book> Books  get; set; 

分别:

var titlesOwnedByUser = context.Set<TitleInformation>()
    .Include(ti => ti.Title)
        .ThenInclude(n => n.Translations)
    .Where(ti => ti.Books.SelectMany(b => b.Owners).Any(bu => bu.UserId == userId));

【讨论】:

以上是关于在实体框架核心中的 SelectMany + Select 之后“包含”不起作用的主要内容,如果未能解决你的问题,请参考以下文章

实体框架核心中的截断表

实体框架核心2.1中的种子关系数据

在实体框架核心中获取最新记录

postgresql jsonb的实体框架核心中的等效数据类型

如何刷新实体框架核心 DBContext?

获取实体框架核心 1.1 的空异常