左边的连接条件

时间:2013-01-08 12:12:23

标签: c# linq entity-framework

使用Linq和EF

一个User可以包含多个RoleUserLinks

如果User的{​​{1}}表包含2条记录,其中一条记录的RoleUserLinkLinkStatusID,另一条记录的DeletedLinkStatusID 1}},下面的查询返回Added。我不想要这个。

如果有User user的{​​{1}} LinkStatusID,请参阅下面的案例3,如何不返回Added

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已删除。用户按预期返回

案例3)用户有2个关联的RoleUserLink条记录。 1的已删除LinkStatusID。用户不应该被退回

2 个答案:

答案 0 :(得分:1)

如果我理解得很好,那应该是:

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()

它会从RoleUserLinks中有LinkStatusId Added的记录的用户中删除不需要的行。

我还将此roleUserLinks.LinkStatus == null更改为roleUserLinks == null以避免NullReferenceException,以防RoleUserLink

没有匹配的User

我测试代码的示例代码

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相关联。

答案 1 :(得分:0)

我通过采用原始查询解决了这个问题:

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);
    }

然后返回此列表。

据我所知,通过这样做,并在网络服务器上进行处理有一个打击,但恕我直言这很容易理解,它的工作原理: - )