8

有人可以给我一个如何使用 LINQ/lambda 表达式执行左连接操作的例子吗?

4

5 回答 5

6

MSDN 上的LINQ to SQL 示例页面提供了如何完成此操作的示例。LINQ to Objects 的代码应该几乎相同。

这里的关键是调用DefaultIfEmpty.

Dim q = From e In db.Employees _
        Group Join o In db.Orders On e Equals o.Employee Into ords = Group _
        From o In ords.DefaultIfEmpty _
        Select New With {e.FirstName, e.LastName, .Order = o}

如果您需要帮助将其转换为 C#,请询问。

于 2009-05-11T15:36:16.563 回答
4

这是LINQ中的左连接示例。

于 2009-05-11T15:37:25.577 回答
0

例如:

IQueryable<aspnet_UsersInRole> q = db.aspnet_Roles
                    .Select(p => p.aspnet_UsersInRoles
                        .SingleOrDefault(x => x.UserId == iduser));

将为您提供来自 asp.net 成员资格的角色列表,其中包含与指定用户不匹配的空值(iduser 键)

于 2010-01-28T18:33:25.547 回答
0

我发现我喜欢的方式是OuterCollection.SelectMany()InnerCollection.DefaultIfEmpty(). 您可以使用“C# 语句”模式在LINQPad中运行以下命令。

var teams = new[] 
    { 
        new { Id = 1, Name = "Tigers" }, 
        new { Id = 2, Name = "Sharks" }, 
        new { Id = 3, Name = "Rangers" },
    };

var players = new[] 
    { 
        new { Name = "Abe", TeamId = 2}, 
        new { Name = "Beth", TeamId = 4}, 
        new { Name = "Chaz", TeamId = 1}, 
        new { Name = "Dee", TeamId = 2}, 
    };

// SelectMany generally aggregates a collection based upon a selector: from the outer item to
//  a collection of the inner item.  Adding .DefaultIfEmpty ensures that every outer item
//  will map to something, even null.  This circumstance makes the query a left outer join.
// Here we use a form of SelectMany with a second selector parameter that performs an
//  an additional transformation from the (outer,inner) pair to an arbitrary value (an
//  an anonymous type in this case.)
var teamAndPlayer = teams.SelectMany(
    team => 
        players
        .Where(player => player.TeamId == team.Id)
        .DefaultIfEmpty(),
    (team, player) => new 
        { 
             Team = team.Name, 
             Player = player != null ? player.Name : null 
        });

teamAndPlayer.Dump();

// teamAndPlayer is:
//     { 
//         {"Tigers", "Chaz"},
//         {"Sharks", "Abe"},
//         {"Sharks", "Dee"},
//         {"Rangers", null}
//     }

在对此进行试验时,我发现有时您可以player在匿名类型的实例化中省略 null 检查。我认为在数据库上使用 LINQ-to-SQL 时就是这种情况(而不是这里的这些数组,我认为这使它成为 LINQ-to-objects 或其他东西。)我认为省略 null 检查在 LINQ 中有效-to-SQL 因为查询被翻译成 SQL LEFT OUTER JOIN,它直接跳到将 null 与外部项目连接起来。(请注意,匿名对象的属性的值必须可以为空;因此,如果您想安全地包含一个int,例如,您需要类似:new { TeamId = (int?)player.TeamId }.

于 2012-10-18T03:43:44.780 回答
0

好吧,我试图重现著名的左连接,其中 b 键为空,我得到的结果是这个扩展方法(有一点想象力,你可以修改它来做一个左连接):

    public static class extends
{
    public static IEnumerable<T> LefJoinBNull<T, TKey>(this IEnumerable<T> source, IEnumerable<T> Target, Func<T, TKey> key)
    {
        if (source == null)
            throw new ArgumentException("source is null");

        return from s in source
               join j in Target on key.Invoke(s) equals key.Invoke(j) into gg
               from i in gg.DefaultIfEmpty()
               where i == null
               select s;
    }
}
于 2015-05-20T21:24:29.967 回答