小编典典

LINQ - 完全外部联接

all

我有一个人的 ID 和他们的名字的列表,以及一个人的 ID 和他们的姓氏的列表。有些人没有名字,有些人没有姓氏;我想对这两个列表进行完全外部联接。

所以下面列出:

ID  FirstName
--  ---------
 1  John
 2  Sue

ID  LastName
--  --------
 1  Doe
 3  Smith

应该产生:

ID  FirstName  LastName
--  ---------  --------
 1  John       Doe
 2  Sue
 3             Smith

我是 LINQ 的新手(如果我跛脚,请原谅我)并且找到了很多“LINQ 外连接”的解决方案,它们看起来都非常相似,但实际上似乎是左外连接。

到目前为止,我的尝试是这样的:

private void OuterJoinTest()
{
    List<FirstName> firstNames = new List<FirstName>();
    firstNames.Add(new FirstName { ID = 1, Name = "John" });
    firstNames.Add(new FirstName { ID = 2, Name = "Sue" });

    List<LastName> lastNames = new List<LastName>();
    lastNames.Add(new LastName { ID = 1, Name = "Doe" });
    lastNames.Add(new LastName { ID = 3, Name = "Smith" });

    var outerJoin = from first in firstNames
        join last in lastNames
        on first.ID equals last.ID
        into temp
        from last in temp.DefaultIfEmpty()
        select new
        {
            id = first != null ? first.ID : last.ID,
            firstname = first != null ? first.Name : string.Empty,
            surname = last != null ? last.Name : string.Empty
        };
    }
}

public class FirstName
{
    public int ID;

    public string Name;
}

public class LastName
{
    public int ID;

    public string Name;
}

但这会返回:

ID  FirstName  LastName
--  ---------  --------
 1  John       Doe
 2  Sue

我究竟做错了什么?


阅读 60

收藏
2022-06-06

共1个答案

小编典典

我不知道这是否涵盖所有情况,从逻辑上讲它似乎是正确的。这个想法是采用左外连接和右外连接,然后对结果进行联合。

var firstNames = new[]
{
    new { ID = 1, Name = "John" },
    new { ID = 2, Name = "Sue" },
};
var lastNames = new[]
{
    new { ID = 1, Name = "Doe" },
    new { ID = 3, Name = "Smith" },
};
var leftOuterJoin =
    from first in firstNames
    join last in lastNames on first.ID equals last.ID into temp
    from last in temp.DefaultIfEmpty()
    select new
    {
        first.ID,
        FirstName = first.Name,
        LastName = last?.Name,
    };
var rightOuterJoin =
    from last in lastNames
    join first in firstNames on last.ID equals first.ID into temp
    from first in temp.DefaultIfEmpty()
    select new
    {
        last.ID,
        FirstName = first?.Name,
        LastName = last.Name,
    };
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);

由于它在 LINQ to Objects 中,因此可以按书面方式工作。如果 LINQ to SQL
或其他,查询处理器可能不支持安全导航或其他操作。您必须使用条件运算符有条件地获取值。

IE,

var leftOuterJoin =
    from first in firstNames
    join last in lastNames on first.ID equals last.ID into temp
    from last in temp.DefaultIfEmpty()
    select new
    {
        first.ID,
        FirstName = first.Name,
        LastName = last != null ? last.Name : default,
    };
2022-06-06