簡體   English   中英

左連接條件在右

[英]Left join condition on right

使用Linq和EF

一個User可以具有多個RoleUserLinks

如果一個UserRoleUserLink表包含2條記錄-一個具有LinkStatusIDDeleted和一個具有LinkStatusIDAdded ,下面的查詢返回的User 我不要這個

如何不返回user如果有任何關聯LinkStatusID的的Added見下文案例3

IEnumerable<User> z =
    (from users in listOfUsersForReviewer
     join roleUserLinks in context.RoleUserLinks
        on users.UserID equals roleUserLinks.UserID into roleUserLinksJoin
     // left join
     from roleUserLinks in roleUserLinksJoin.DefaultIfEmpty()
     where
         // case 1 - has never been added to a role ie record isn't there
         roleUserLinks.LinkStatus == null
         // case 2 - has been soft deleted from a role so we want this record
         || roleUserLinks.LinkStatusID == (byte)Enums.LinkStatus.Deleted
     select users).Distinct();

情況1)用戶沒有關聯的RoleUserLink記錄。 用戶按預期返回

情況2)用戶具有1個關聯的RoleUserLink記錄,且LinkStatusID為Deleted。 用戶按預期返回

情況3)用戶具有2個關聯的RoleUserLink記錄。 1的LinkStatusID為Deleted。 用戶不應返回

如果我理解得不錯,應該是:

IEnumerable<User> z =
    (from users in listOfUsersForReviewer
     join roleUserLinks in context.RoleUserLinks
        on users.UserID equals roleUserLinks.UserID into roleUserLinksJoin
     // left join
     from roleUserLinks in roleUserLinksJoin.DefaultIfEmpty()
     where
         (roleUserLinks == null
         || roleUserLinks.LinkStatusID == (byte)Enums.LinkStatus.Deleted)
         && !roleUserLinksJoin.Where(x=> roleUserLinks.LinkStatusID == (byte)Enums.LinkStatus.Added && x.UserID == roleUserLinks.UserID).Any()
     select users).Distinct();

我添加了這個子查詢:

&& !roleUserLinksJoin.Where(x=> roleUserLinks.LinkStatusID == (byte)Enums.LinkStatus.Added && x.UserID == roleUserLinks.UserID).Any()

對於已AddedLinkStatusId RoleUserLinks中已記錄的用戶,它將從結果中刪除不需要的行。

我還將此roleUserLinks.LinkStatus == null更改為roleUserLinks == null以避免NullReferenceException的情況下,如果沒有與User匹配的RoleUserLink

我在其上測試代碼的示例代碼

static void Main(string[] args)
{
    var usersList = new List<User>()
                    {
                        new User() {UserID = 1},
                        new User() {UserID = 2},
                        new User() {UserID = 3}
                    };

    var userLinksList = new List<RoleUserLink>()
                        {
                            new RoleUserLink() {UserID = 1, State = "del"},
                            new RoleUserLink() {UserID = 2, State = "add"},
                            new RoleUserLink() {UserID = 2, State = "del"}
                        };

    IEnumerable<User> z = (from users in usersList 
                           join roleUserLinks in userLinksList
                           on users.UserID equals roleUserLinks.UserID into roleUserLinksJoin
                           // left join
                           from roleUserLinks in roleUserLinksJoin.DefaultIfEmpty()
                           where
                            // has never been added to a role ie record isn't there
                                roleUserLinks == null
                            // has been soft deleted from a role so we want this record
                                || roleUserLinks.State == "del"
                            // has been added to role so we don't want this record
                                && !roleUserLinksJoin.Where(x=> x.State == "add" && x.UserID == roleUserLinks.UserID).Any()
                            select users).Distinct();
    var res = z.ToList();

}

public class User
{
    public int UserID { get; set; }
}

public class RoleUserLink
{
    public int UserID { get; set; }
    public string State { get; set; }
} 

它返回ID為1和3的用戶。 UserId:1僅具有狀態為delete鏈接。 UserId:3沒有任何鏈接。 並且不返回UserId:2因為它還具有狀態add鏈接。

我通過采用原始查詢解決了這個問題:

IEnumerable<User> z =
    (from users in listOfUsersForReviewer
     join roleUserLinks in context.RoleUserLinks
        on users.UserID equals roleUserLinks.UserID into roleUserLinksJoin
     // left join
     from roleUserLinks in roleUserLinksJoin.DefaultIfEmpty()
     where
         // case 1 - has never been added to a role ie record isn't there
         roleUserLinks.LinkStatus == null
         // case 2 - has been soft deleted from a role so we want this record
         || roleUserLinks.LinkStatusID == (byte)Enums.LinkStatus.Deleted
     select users).Distinct().Include(b => b.RoleUserLinks).ToList();

並在末尾添加了Include和ToList。

然后:

var list = new List<User>();

    foreach (var user in z)
    {
        bool shouldReturnUser = true;
        //get roleLinks
        foreach (var rul in user.RoleUserLinks)
        {
            if (rul.LinkStatusID == (byte) Enums.LinkStatus.Added)
                shouldReturnUser = false;
        }
        if (shouldReturnUser)
            list.Add(user);
    }

然后返回此列表。

我知道這樣做和在Web服務器上進行處理都會造成性能下降,但是恕我直言,這非常容易理解,並且可以:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM