【问题标题】:EF Core join on sub table子表上的 EF Core 联接
【发布时间】:2021-07-17 12:54:28
【问题描述】:

我设置了三个类,如下所示:

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 中的表之间应该已经存在关系感觉不对

【问题讨论】:

    标签: c# sql-server asp.net-core entity-framework-core ef-core-5.0


    【解决方案1】:

    您还需要向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);
    

    【讨论】:

    • 太棒了,谢谢。我之前已经将导航添加到UserItem,但作为集合而不是对象并且没有考虑替代方案。我删除了 UserItem 中的其他字段以使示例更清晰,但很高兴知道我不需要那样链接。
    猜你喜欢
    • 1970-01-01
    • 2018-06-21
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2021-03-03
    • 2021-11-16
    相关资源
    最近更新 更多