I’m using EF 5 rc on VS 2012 RC and got some issues. Pretty sure it’s got to do with my knowledge in databases and EF than the version numbers of the software I use 🙂
So, I have 3 classes. User, Role and Right.
User class
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
}
Right Class
public class Right
{
public virtual int RightId { get; set; }
public virtual string Description { get; set; }
}
Role Class
public class Role
{
public virtual int RoleId { get; set; }
public virtual string Description { get; set; }
public virtual ICollection<Right> Rights { get; set; }
}
Context
class MyContext : DbContext
{
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<Right> Rights { get; set; }
}
Now, I want to add roles to a user, and rights to a role. But I also want to make sure it’s possible to add the same Right can be added to different 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();
I’m getting
InvalidOperationException: Multiplicity constraint violated. The role ‘Role_Rights_Source’ of the relationship ‘Role_Rights’ has multiplicity 1 or 0..1.
What am I doing wrong ?
Also, I don’t feel right about creating a new list like
role1.Rights = new List<Right>();
role2.Rights = new List<Right>();
What’s the recommended way to do this ? Rights property is null. So I can’t add anything to it without newing it up.
The problem is the convention used by EF to infer the relation. It thinks that the relation is one-to-many but you want many-to-many (role can have multiple rights and the right can be used in multiple roles).
There are two options to solve this:
Option 1: Create navigation property in Right:
Now EF convention will detect the collection on both sides of the relation and correctly use many-to-many multiplicity instead of one-to-many
Option 2: Use Fluent-API to tell EF that you want many-to-many relation:
Now EF knows that the
Rightcan be assigned to multiple roles even through theRightdoesn’t have navigation property toRole.If the
Rolecan be assigned to multiple users you will have to use many-to-many relation as well