如何在不使用 join-on-equals-into
子句的情况下在C#LINQ中对对象执行左外连接?用 where
子句有没有办法做到这一点?正确的问题:对于内连接很容易,我有这样的解决方案
List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key
select new JoinPair { LeftId = l.Id, RightId = r.Id})
但对于左外连接我需要一个解决方案 . 我是这样的,但它不起作用
List< JoinPair> leftFinal = (from l in lefts from r in rights
select new JoinPair {
LeftId = l.Id,
RightId = ((l.Key==r.Key) ? r.Id : 0
})
JoinPair是一个类:
public class JoinPair { long leftId; long rightId; }
19 回答
这是与LINQ比较的SQL语法内外连接的语法 . 左外连接:
http://www.ozkary.com/2011/07/linq-to-entity-inner-and-left-joins.html
“以下示例在产品和类别之间进行组连接 . 这实际上是左连接 . 即使类别表为空,into表达式也会返回数据 . 要访问类别表的属性,我们现在必须从可枚举的结果中进行选择通过在catList.DefaultIfEmpty()语句中添加from cl .
LEFT OUTER JOIN 的简单解决方案:
notes :
要提高性能,可以将SetB转换为 Dictionary (如果已完成,则必须更改此项: !setB.Contains(stA.Id) )或 HashSet
当涉及多个字段时,可以使用 Set 操作和实现的类来实现: IEqualityComparer
看看这个example . 此查询应该有效:
有三个表格:人员,学校和人员学校,它们将人们与他们所在的学校联系起来 . 在表人员学校中没有提到id = 6的人 . 但是,id = 6的人在结果lef-joined网格中显示 .
使用lambda表达式
通过扩展方法实现左外连接可能看起来像
然后resultselector必须处理null元素 . FX .
Necromancing .
如果使用数据库驱动的LINQ提供程序,则可以如下编写更易读的左外连接:
如果省略
DefaultIfEmpty()
,则会有内连接 .接受接受的答案:
这种语法非常混乱,当你想要离开连接MULTIPLE表时,它是如何工作的还不清楚 .
Note
应该注意的是
from alias in Repo.whatever.Where(condition).DefaultIfEmpty()
与外部应用/左连接 - 横向相同,任何(体面的)数据库优化器完全能够转换为左连接,只要你不在Linq中执行此操作即可 . -2对象(因为在使用Linq-to-Objects时没有DB优化器) .Detailed Example
当与LINQ 2 SQL一起使用时,它将很好地转换为以下非常清晰的SQL查询:
Edit:
有关更复杂的示例,另请参阅“Convert SQL Server query to Linq query” .
另外,如果你在Linq-2-Objects(而不是Linq-2-SQL)中进行它,你应该采用老式的方式(因为LINQ to SQL正确地将它转换为连接操作,但是对于这个方法的对象)强制完全扫描,并没有利用索引搜索,为什么...):
这是一般形式(已在其他答案中提供)
不过这里有一个解释,我希望能澄清这实际意味着什么!
实际上创建了一个单独的结果集b_temp,它有效地包含右侧条目的空“行”(“b”中的条目) .
然后是下一行:
..对结果集进行设置,在右侧设置'row'的默认空值,并将右侧行连接的结果设置为'b_value'的值(即右边的值)手边,如果有匹配的记录,或者'null',如果没有) .
现在,如果右侧是单独的LINQ查询的结果,它将由匿名类型组成,它们只能是“某事”或“空” . 如果它是一个可枚举的(例如一个List - 其中MyObjectB是一个有2个字段的类),那么就可以具体说明默认的'null'值用于它的属性:
这确保'b'本身不为null(但是它的属性可以为null,使用您指定的默认空值),这允许您检查b_value的属性而不会获得b_value的空引用异常 . 请注意,对于可为空的DateTime,必须在“DefaultIfEmpty”的规范中将(DateTime?)的类型(即“可空的DateTime”)指定为null的“Type”(这也适用于非本机的类型) '可空,例如双,漂浮) .
您只需链接上述语法即可执行多个左外连接 .
在linq中执行左外连接C#//执行左外连接
https://dotnetwithhamid.blogspot.in/
如果您需要加入并过滤某些内容,可以在联接之外完成 . 可以在创建集合后完成过滤 .
在这种情况下,如果我在连接条件中执行此操作,我会减少返回的行 .
使用三元条件
(= n == null ? "__" : n.MonDayNote,)
如果对象是
null
(因此不匹配),则返回?
之后的内容 .__
,在这种情况下 .否则,返回
:
之后的内容,n.MonDayNote
.感谢其他贡献者,我从自己的问题开始 .
看看这个例子
现在你能够
include elements from the left
即使那个元素has no matches in the right
,在我们的例子中我们已经重新获得Arlene
,即使他在右边没有匹配这是参考
How to: Perform Left Outer Joins (C# Programming Guide)
如上所述:
101 LINQ Samples - Left outer join
扩展方法,类似于左连接和Join语法
刚刚在.NET核心中编写它,它似乎按预期工作 .
小测试:
我想补充一点,如果你得到MoreLinq扩展,现在支持同源和异构左连接
http://morelinq.github.io/2.8/ref/api/html/Overload_MoreLinq_MoreEnumerable_LeftJoin.htm
例:
编辑:
回想起来,这可能有效,但它将IQueryable转换为IEnumerable,因为morelinq不会将查询转换为SQL .
您可以使用此处所述的GroupJoin:https://stackoverflow.com/a/24273804/4251433
这将确保它保持为IQueryable,以防您以后需要对其进行进一步的逻辑操作 .
OUTPUT
现在作为扩展方法:
使用就像你通常使用join一样:
希望这能为您节省一些时间 .
如果您需要加入两个以上的表,这是一个示例:
参考:https://stackoverflow.com/a/17142392/2343
这是一个使用方法语法的相当容易理解的版本: