[英]Left join condition on right
使用Linq和EF
一個User
可以具有多個RoleUserLinks
。
如果一個User
的RoleUserLink
表包含2條記錄-一個具有LinkStatusID
的Deleted
和一個具有LinkStatusID
的Added
,下面的查詢返回的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()
對於已Added
了LinkStatusId
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.