获取只有一个管理员的项目,该管理员是给定用户



我有以下实体:

public class Project {
public Int32 Id { get; set; }
public ICollection<ProjectRole> ProjectRoles { get; set; }
}
public class User {
public Int32 Id { get; set; }
public ICollection<ProjectRole> ProjectRoles { get; set; }
}
public class ProjectRole {
public Int32 ProjectId { get; set; }
public Int32 UserId { get; set; }
public String Role { get; set; }
public Project Project { get; set; }
public User User { get; set; }
}

给定一个userId我需要找到所有项目:
1.只有一个ProjectRoleRole等于Admin;
2.AdminUserId等于给定的userId

var userId = 1;
var projects = context.Projects.Where(x => x.ProjectRoles.Count(y => y.Role == "Admin") == 1 && ??

我首先获取只有一个角色等于Admin的所有项目。

我缺少的是确保ProjectRole的UserId等于给定的userId

我该怎么做?

这个问题比最初看起来更有趣,主要是因为有许多简单的解决方案,但它们只需要为每个项目执行 2 个子查询才能满足 2 个要求。

例如,由于

x.ProjectRoles.Count(y => y.Role == "Admin")

条件确保每个项目只有 1 个管理员,附加条件如

&& x.ProjectRoles.Any(y => y.Role == "Admin" && y.UserId == userId)

&& x.ProjectRoles.FirstOrDefault(y => y.Role == "Admin").UserId == userId

&& x.ProjectRoles.Where(y => y.Role == "Admin").Select(y => y.UserId).Contains(userId)

将确保单个管理员是给定用户。

另一种方法是使用这样的标准

x.ProjectRoles.Any(y => y.Role == "Admin" && y.UserId == userId)
&& !x.ProjectRoles.Any(y => y.Role == "Admin" && y.UserId != userId)

换句话说,项目将给定的用户作为管理员,而没有其他管理员。

实际上可以删除y.UserId == userId条件

x.ProjectRoles.Any(y => y.Role == "Admin")
&& !x.ProjectRoles.Any(y => y.Role == "Admin" && y.UserId != userId)

即项目有管理员,除了给定用户之外也没有其他管理员,因此它只有 1 个管理员,它是给定的用户。

无论如何,如开头所述,所有这些项目都为每个项目执行 2 个子查询。 现在,如果您想知道(这对我来说是有趣的部分(是否通过单个子查询实现,答案是肯定的,条件如下:

x.ProjectRoles.Where(y => y.Role == "Admin")
.Min(y => y.UserId == userId ? (int?)1 : 0) == 1

原因如下。在Where子句之后,我们有项目的管理员集。现在表达式

.Min(y => y.UserId == userId ? 1 : 0)

会回来

  • null集为空时(没有管理员(
  • 0 当有给定用户以外的管理员时
  • 1 当给定用户是管理员并且没有其他管理员时

如我们所见,只有返回值1满足这两个要求,因此== 1将实现所需的过滤。

试试这个:

context.ProjectRoles
.GroupBy(p => new { p.Role, p.UserId })
.Where(g => g.Key.Role == "Admin" &&
g.Count() == 1 &&
g.All(z => z.UserId == userId)
);

相关内容

  • 没有找到相关文章

最新更新