C# 如何编写涉及多对多关系的EF查询
我对使用实体框架非常陌生,我很难理解如何编写使用多对多关系的查询。我有3个实体角色、用户和安全。一个角色可以有多个安全角色,一个安全角色可以分配给多个角色。一个角色可以有多个用户,一个用户可以有多个角色 我的问题是:如何编写一个查询,为给定的用户ID提供一个不同的安全列表? 这是我的模型,EF会自动为我创建链接表C# 如何编写涉及多对多关系的EF查询,c#,.net,entity-framework,entity-framework-4.1,C#,.net,Entity Framework,Entity Framework 4.1,我对使用实体框架非常陌生,我很难理解如何编写使用多对多关系的查询。我有3个实体角色、用户和安全。一个角色可以有多个安全角色,一个安全角色可以分配给多个角色。一个角色可以有多个用户,一个用户可以有多个角色 我的问题是:如何编写一个查询,为给定的用户ID提供一个不同的安全列表? 这是我的模型,EF会自动为我创建链接表 public class SecurityContext : DbContext { public DbSet<User> Users { get; set; }
public class SecurityContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Securable> Securables { get; set; }
}
public class User
{
public Guid UserId { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Securable
{
public Guid SecurableId { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Roles { get;set;}
}
public class Role
{
public Guid RoleId { get; set; }
public string Name { get; set; }
public virtual ICollection<Securable> Securables { get; set; }
public virtual ICollection<User> Users { get; set; }
}
公共类SecurityContext:DbContext
{
公共数据库集用户{get;set;}
公共数据库集角色{get;set;}
公共数据库集安全性{get;set;}
}
公共类用户
{
公共Guid用户标识{get;set;}
公共字符串名{get;set;}
公共字符串姓氏{get;set;}
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公共虚拟ICollection角色{get;set;}
}
公务舱保安
{
公共Guid安全ID{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection角色{get;set;}
}
公共阶级角色
{
公共Guid RoleId{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection安全文件{get;set;}
公共虚拟ICollection用户{get;set;}
}
像这样吗
User user = ...;
IEnumerable<Securable> securablesForUser =
user.Roles.SelectMany(x => x.Securables).Distinct();
使用WHERE EXISTS
,这在我们的基准测试中比查询两次要慢
一如既往,如果您有性能问题,我建议您进行评测。结果可能与您的数据不同如果您不太在意个人资料,那么您也不太在意优化未经测试,但在我的脑海中,它会是这样的:
var context = new DbContext();
var result = context.Securables
.Where(s => s.Roles
.Any(r => r.Users
.Any(u => u.UserId = userId)))
.Distinct();
嗯,这是一个简单的解决方案,但我假设只有在启用了延迟加载的情况下才能工作?此外,这还需要两个sql查询,一个用于获取用户,另一个用于获取安全性?如果这是性能瓶颈,您可以在加载用户时立即加载角色和安全性。除非你正在显示一个用户列表,否则我可能不会麻烦你。不,这个查询在没有延迟加载的情况下运行良好。它甚至可以在EF1中工作。急切的加载不会有帮助;一切正常。这看起来像是个赢家,我明天会测试一下
IEnumerable<Securable> securablesForUser = context.Securables.Where(
x => x.Roles.Any(y => y.Users.Any(z => z.UserId == userId))).Distinct();
var context = new DbContext();
var result = context.Securables
.Where(s => s.Roles
.Any(r => r.Users
.Any(u => u.UserId = userId)))
.Distinct();