首页 > 解决方案 > Linq 和左连接

问题描述

我有以下型号:

public class UserPage
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
    public string Path { get; set; }
    public string Icon { get; set; }
}

public class UserPageSetting
{
    public int UserId { get; set; }
    public int PageId { get; set; }
    public bool Active { get; set; } = true;
    public bool Published { get; set; } = true;
    public DateTime? Modified { get; set; }

    public virtual UserPage UserPage { get; set; }
}

UserPage收藏有 5 条记录,UserPageSetting有 1 条记录。我需要有 5 条记录和不存在记录的默认值的结果。

我尝试这样做:

var list = (from userPage in _dbContext.UserPages
           join userPageSetting in _dbContext.UserPageSettings on userPage.Id equals userPageSetting.PageId
           into gj
            from subUserPageSetting in gj.DefaultIfEmpty()
            where subUserPageSetting.UserId == userId
           select new UserPageSettingDto { Active = subUserPageSetting.Active, Modified = subUserPageSetting.Modified, Id = userPage.Id, Icon = userPage.Icon, IsSelected = userPage.IsSelected,
               Name = userPage.Name, Path = userPage.Path, Published = subUserPageSetting.Published
           }).ToList();

但结果我只看到一条记录。我的代码有什么问题?

标签: c#linqjoin

解决方案


这是一个如何进行左连接并UserPageSetting在连接失败时创建默认值的示例。这将返回 5 条记录;每个 1 个UserPage。其中之一将成功加入Active = true

void Main()
{
    var inner = new List<UserPage> {
        new UserPage { Id = 1, Name = "One" },
        new UserPage { Id = 2, Name = "Two" },
        new UserPage { Id = 3, Name = "Three" },
        new UserPage { Id = 4, Name = "Four" },
        new UserPage { Id = 5, Name = "Five" }};

    var outer = new List<UserPageSetting> {
        new UserPageSetting { UserId = 1, PageId = 1, Active = true, Published = true }};

    var joined = inner
        .GroupJoin(outer, i => i.Id, o => o.PageId, (i, o) => o
               .Select(x => new { Inner = i, Outer = x })
               .DefaultIfEmpty(new { Inner = i, Outer = new UserPageSetting {UserId = i.Id, PageId = i.Id, Active = false, Published = false } }))
        .SelectMany(x => x)
        //.Where(x => x.Outer == -1) -- include if you only want to see the join misses
        ;

    foreach (var x in joined)
    {
        Console.WriteLine($"UserPage({x.Inner.Id}, {x.Inner.Name}) joined to UserPageSetting({x.Outer.UserId}, {x.Outer.Active})");
    }
}

这将输出以下内容:

UserPage(1, One) joined to UserPageSetting(1, True)
UserPage(2, Two) joined to UserPageSetting(2, False)
UserPage(3, Three) joined to UserPageSetting(3, False)
UserPage(4, Four) joined to UserPageSetting(4, False)
UserPage(5, Five) joined to UserPageSetting(5, False)

推荐阅读