简体   繁体   English

我如何将“或”运算符引入 linq 查询连接

[英]How and I introduce an "or" operator into a linq query join

What is the syntax introduce an "or" operator into a linq query join.将“或”运算符引入 linq 查询连接的语法是什么。 It doesn't seem to like "||", "or"?它似乎不喜欢“||”、“或”? I need to join one foreign key against two possible keys from the users table.我需要将一个外键与来自 users 表的两个可能的键连接起来。

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

Without the or portion, this works but missing the extra key没有 or 部分,这有效但缺少额外的键

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

So you have a database with at least two tables: Users and UserDocuments .因此,您有一个包含至少两个表的数据库: UsersUserDocuments Every UserDocument has a property fkDocumentId .每个UserDocument都有一个属性fkDocumentId

Although you didn't say so, it seems to me that this is a foreign key to elements in table Users .虽然你没有这么说,但在我看来,这是表Users元素的外键。 Apparently this foreign key refers sometimes to User.TransportUserId and sometimes to User.WorkUserId .显然,这个外键有时指的是User.TransportUserId ,有时指的是User.WorkUserId

Are you sure you want this?你确定要这个吗? If fkDocumentId has a value 10, does it refer to the User with a TransportId equal to 10, or to the user with WorkUserId equal to 10, or both?如果fkDocumentId的值为 10,它是指 TransportId 等于 10 的用户,还是 WorkUserId 等于 10 的用户,或两者兼而有之?

Anyway, if you investigate Enumerable.Join, then you will find that you provide two keySelectors: one to select a key from Users, and one to select a key from UserDocuments.无论如何,如果您调查Enumerable.Join,那么您会发现您提供了两个 keySelector:一个从 Users 中选择一个键,另一个从 UserDocuments 中选择一个键。 When these two keys are equal, then the ResultSelector parameter is used to construct your joined element.当这两个键相等时,将使用 ResultSelector 参数来构造您的连接元素。

The problem is in the words "are equal".问题在于“平等”这个词。 You'll have to make sure that you select your keys and provide an IEqualityComparer such that the keys will be considered equal.您必须确保选择您的密钥并提供一个 IEqualityComparer,以便这些密钥被认为是相等的。

Another more easy method would be to create a new Join extension method.另一种更简单的方法是创建一个新的 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;
        }
    }
}

Usage:用法:

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,
        ...
    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM