有人能举例说明如何使用LINQ / lambda表达式执行左连接操作吗?
答案 0 :(得分:6)
MSDN上的LINQ to SQL samples page给出了如何实现此目的的示例。对于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#,请询问。
答案 1 :(得分:4)
这是LINQ中的example of a left join。
答案 2 :(得分:0)
例如:
IQueryable<aspnet_UsersInRole> q = db.aspnet_Roles
.Select(p => p.aspnet_UsersInRoles
.SingleOrDefault(x => x.UserId == iduser));
将为您提供asp.net成员资格中的角色列表,其中null与指定用户不匹配(iduser密钥)
答案 3 :(得分: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
的空值检查。我认为在数据库上使用LINQ-to-SQL时就是这种情况(而不是这里的这些数组,我认为这使得它成为LINQ到对象之类的东西。)我认为在LINQ中省略了null检查-to-SQL因为查询被转换为SQL LEFT OUTER JOIN
,它直接跳过与外部项连接null。 (请注意,匿名对象的属性值必须是可空的;因此,如果您想安全地包含int
,那么您需要:new { TeamId = (int?)player.TeamId }
。
答案 4 :(得分:0)
我试图重现着名的左连接,其中b键为null,我得到的结果就是这种扩展方法(只需要一点点想象力就可以将它修改为只做左连接):
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;
}
}