实体框架和关系
Posted
技术标签:
【中文标题】实体框架和关系【英文标题】:Entity Framework and relationships 【发布时间】:2012-07-23 10:52:17 【问题描述】:我在 VS 2012 RC 上使用 EF 5 rc 并遇到了一些问题。很确定这与我在数据库和 EF 方面的知识有关,而不是我使用的软件的版本号 :)
所以,我有 3 节课。用户、角色和权利。
用户类
public class User
[Key]
public int UserId get; private set;
[Required]
public string EmailAddress get; internal set;
[Required]
public string Username get; internal set;
public ICollection<Role> Roles get; set;
// More properties
正确的类
public class Right
public virtual int RightId get; set;
public virtual string Description get; set;
角色类
public class Role
public virtual int RoleId get; set;
public virtual string Description get; set;
public virtual ICollection<Right> Rights get; set;
上下文
class MyContext : DbContext
public virtual DbSet<User> Users get; set;
public virtual DbSet<Role> Roles get; set;
public virtual DbSet<Right> Rights get; set;
现在,我想将 roles 添加到 user,并将 rights 添加到 role。但我也想确保可以添加相同的Right 可以添加到不同的roles。
var role1 = new Role()
Description = "role1"
;
var role2 = new Role()
Description = "role2"
;
var right = new Right()
Description = "right"
;
context.Rights.Add(right);
context.Roles.Add(role1);
context.Roles.Add(role2);
role1.Rights = new List<Right>();
role2.Rights = new List<Right>();
role1.Rights.Add(right);
role2.Rights.Add(right);
/**** ERROR ****/
context.SaveChanges();
我来了
InvalidOperationException:违反多重性约束。关系“Role_Rights”的角色“Role_Rights_Source”具有多重性 1 或 0..1。
我做错了什么? 另外,我对创建一个像
这样的新列表感觉不妥 role1.Rights = new List<Right>();
role2.Rights = new List<Right>();
推荐的方法是什么?权利属性为空。所以我不能在不更新的情况下添加任何东西。
【问题讨论】:
【参考方案1】:问题在于 EF 用于推断关系的约定。它认为关系是一对多但你想要多对多(角色可以有多个权限,并且权限可以用于多个角色)。
有两种方法可以解决这个问题:
选项 1:在右侧创建导航属性:
public class Right
public virtual int RightId get; set;
public virtual string Description get; set;
public virtual ICollection<Role> Roles get; set;
现在 EF 约定将检测关系两侧的集合并正确使用多对多多重性而不是一对多
选项 2:使用 Fluent-API 告诉 EF 您需要多对多关系:
public class MyContext : DbContext
public virtual DbSet<User> Users get; set;
public virtual DbSet<Role> Roles get; set;
public virtual DbSet<Right> Rights get; set;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
modelBuilder.Entity<Role>()
.HasMany(r => r.Rights)
.WithMany();
现在 EF 知道 Right
可以分配给多个角色,即使 Right
没有 Role
的导航属性。
如果Role
可以分配给多个用户,您也必须使用多对多关系
【讨论】:
哇,您刚刚解决了过去 3 天让我无法入睡的问题。 (显示我对 EF 有多么出色。)我假设,使用 选项 1 如果我将角色添加到权限,EF 还将映射该角色将拥有权限? 是 - EF 将在数据库内部创建联结表以处理多对多关系。【参考方案2】:Ladislav 的答案应该可以很好地解决该错误。
关于您对使用感到不舒服的问题:
role1.Rights = new List<Right>();
您应该在构造函数中将这些属性初始化为新的列表,然后将为所有角色实例完成:
public class Role
public virtual int RoleId get; set;
public virtual string Description get; set;
public virtual ICollection<Right> Rights get; set;
public Role ()
this.Rights = new List<Right>();
【讨论】:
非常感谢...这将为我节省很多空检查... :) 如果你需要很多,不要在你用模型生成数据库之后。只需通过从数据库重新创建模型来向后工作,EF 也会使用一些 Fluent 映射自动添加这些 sql-server-performance.com/2012/…以上是关于实体框架和关系的主要内容,如果未能解决你的问题,请参考以下文章