子表上的 EF Core 连接

问题描述

我设置了三个类:

public class Item
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<UserItem> UserItems { get; set; }
}

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<UserItem> UserItems { get; set; }
}

public class UserItem
{
    public int ID { get; set; }
    public int UserID { get; set; }
    public int ItemID { get; set; }
}

Entity Framework 使用正确的外键在 sql Server 数据库生成表。我可以查询 ItemUser获取 UserItem 集合,如下所示:

var a = context.DBUser.Include(s => s.UserItems);
var b = context.DBItem.Include(s => s.UserItems);

我不满意的是我如何从 UserItem。在 sql 中,我会做这样的事情

SELECT * FROM Users U
LEFT JOIN UserItems UI
    ON U.ID = UI.UserID
LEFT JOIN Items I
    ON UI.ItemID = I.ID

在 C# 中,我需要求助于这个:

var c = from user in _context.DBUsers
    join userItem in _context.DBUserItems
        on user.ID equals userItem.UserID into ui
        from userItem in ui.DefaultIfEmpty()
    join item in _context.DBItems
        on userItem.ItemID equals item.ID into i
        from item in i.DefaultIfEmpty()
    select new
    {
        user,userItem,item
    };

鉴于EF中的表之间应该已经存在关系,这感觉不对

解决方法

您还需要向 UserItem 添加导航:

public class UserItem
{
    public int ID { get; set; }
    public int UserID { get; set; }
    public int ItemID { get; set; }

    public User User { get; set; }
    public Item Item { get; set; }
}

那么你的查询可以是这样的:

var users = context.DBUser
    .Include(x => x.UserItems)
    .ThenInclude(x => x.Item);

另请注意,如果您使用的是 .NET 5,则可以完全省略 UserItem“加入实体”:

public class Item
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Item> Items { get; set; }
}

这将简化您的查询:

var users = context.DBUser.Include(x => x.Items);