语法是什么?在linq查询联接中引入“或”运算符。它似乎不喜欢“ ||”,“或”吗?我需要将一个外键与用户表中的两个可能的键连接起来。
var thirdQuery = (from u in tbl_users
join ua in tbl_userDocuments on (u.TransportUserID equals ua.fkDocumentID
|| u.WorkUserID equals ua.fkDocumentID) into uaGroup
from uaTrans in uaGroup.DefaultIfEmpty()
join ul in tbl_user_logins on uaTrans.fkUserID equals ul.user_login_id_pk into ulGroup
没有或部分,这有效,但缺少额外的密钥
var thirdQuery = (from u in tbl_users
join ua in tbl_userDocuments on (u.TransportUserID equals ua.fkDocumentID) into uaGroup
from uaTrans in uaGroup.DefaultIfEmpty()
join ul in tbl_user_logins on uaTrans.fkUserID equals ul.user_login_id_pk into ulGroup
最佳答案
因此,您有一个至少包含两个表的数据库:Users
和UserDocuments
。每个UserDocument
都有一个属性fkDocumentId
。
尽管您没有这么说,但在我看来,这是表Users
中元素的外键。显然,此外键有时是指User.TransportUserId
,有时是指User.WorkUserId
。
您确定要这个吗?如果fkDocumentId
的值为10,它是引用TransportId等于10的用户还是引用WorkUserId等于10的用户,还是两者都引用?
无论如何,如果您调查Enumerable.Join,,则会发现您提供了两个keySelector:一个用于从Users中选择密钥,另一个用于从UserDocuments中选择密钥。当这两个键相等时,则使用ResultSelector参数构造您的联接元素。
问题在于“等于”一词。您必须确保选择密钥并提供IEqualityComparer,以使密钥被视为相等。
另一个更简单的方法是创建新的Join扩展方法。
IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> Join(
this IEnumerable<TSource> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector1,
Func<TOuter, TKey> outerKeySelector2,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
// make two lookup tables from Outer: one for key1 and one for key2:
var lookup1 = outer.ToLookup( outerElement => outerKeySelector1(outerElement));
var lookup2 = outer.ToLookup( outerElement => outerKeySelector2(outerElement));
// so if you have a TKey from the innerKeySelector, you can find if it matches key1 or key2
foreach (TInner innerElement in inner)
{
TKey innerKey = innerKeySelector(innerElement)
var matchingElementsKey1 = lookup1[innerKey];
var matchineElementsKey2 = lookup2[innerKey];
var allmatchingElements = matchingElementsKey1.Concat(matchingElementsKey2);
foreach(var matchingElement in allMatchingElements)
{
TResult result = resultSelector(matchingElement, innerElement);
yield return result;
}
}
}
用法:
var result = tblUsers.Join(tblUserDocuments,
user => user.TransportUserId, // select outerKey1
user => user.WorkUserId, // select outerKey2
document => document.fkDocumentId, // select innerKey
// when inner key matches either outerKey1, or outerKey2, create one new object:
(user, document) => new
{
// Select the user documents that you want:
UserId = user.Id,
Name = user.Name,
...
// Select the document properties that you want:
DocumentId = document.Id,
Author = document.Author,
PublishedDate = document.Date,
...
})