我有一份身份证和名字的 list ,还有一份身份证和姓氏的 list .有些人没有名字,有些人没有姓氏;我想在这两个列表上做一个完整的外部连接.

因此,下面列出了以下列表:

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

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

应产生:

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

我是LINQ的新手(如果我是跛脚的话,请原谅我),我已经找到了很多关于"LINQ外部联接"的解决方案,它们看起来非常相似,但实际上似乎是左外部联接.

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

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

我做错了什么?

推荐答案

我不知道这是否涵盖了所有情况,从逻辑上看,这似乎是正确的.这个 idea 是取左外连接和右外连接,然后取结果的并集.

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或Other,则查询处理器可能不支持安全导航或其他操作.您必须使用条件运算符来有条件地获取这些值.

即,

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,
    };

.net相关问答推荐

从Couchbase删除_txn文档的推荐方法?""

Azure管道-使用.NET 8 RC2 SDK生成C#项目失败

PowerShell - 如果用户输入凭据,则查询 AD 时出错

代码访问安全是否在任何现实世界中使用?

如何将 Javascript 日期时间转换为 C# 日期时间?

调整小数精度,.net

C# 是否(或将)包含用于副作用验证的功能?

实例化具有运行时确定类型的对象

.NET 4.0 中有内置的二叉搜索树吗?

读取方法的属性值

什么版本的 .NET 附带什么版本的 Windows?

我不了解应用程序域

ASP.NET Core (.NET Core) 和 ASP.NET Core (.NET Framework) 的区别

找不到库 hostpolicy.dll

如何在 nuspec 中指定特定的依赖版本?

为什么要使用 C# 类 System.Random 而不是 System.Security.Cryptography.RandomNumberGenerator?

绑定在代码隐藏中定义的对象

判断任意字符串是否为有效文件名的最简单方法

模拟和单元测试需要时如何抛出 SqlException?

System.ServiceModel 在 .NET Core 项目中找不到