问题
I'm have this Many To Many Relationship:
public class Role
{
[Key]
public int role_Id { get; set; }
public string Name { get; set; }
public ICollection<LoginModel> Users { get; set; }
public ICollection<Permission> Permissions { get; set; }
public Role()
{
Users = new List<LoginModel>();
Permissions = new Collection<Permission>();
}
}
public class Permission
{
[Key]
public int permi_Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public Permission()
{
Roles = new Collection<Role>();
}
}
In my DbContext
modelBuilder.Entity<Role>().HasMany(r => r.Permissions).WithMany(p => p.Roles)
.Map(
m =>
{
m.MapLeftKey("role_id");
m.MapRightKey("per_id");
m.ToTable("roles_permissions");
}
);
So I have this third table (Many To Many) and I want to Update the permissions (Add or remove) for a specific Role ( The permissions are taken from a CheckedListBox).I'm trying to update the third table with this code but it does not work
//Get the specific role
Role role = (from s in db.Roles
where s.Name == txt_modificar_nombre.Text
select s).FirstOrDefault<Role>();
//Get the permissions from that specific role
var permissions = db.Roles.Where(r => r.Name == txt_modificar_nombre.Text)
.SelectMany(r => r.Permissions);
//erase all the old permissions (like reset the permissions)
foreach (var permission in permissions)
{
role.Permissions.Remove(permission);//reset the permissions
for (int i = 0; i < checkedListBox_modificar_permissions.Items.Count; i++)
{
if ((string)checkedListBox_modificar_permissions.Items[i] == permission.Name)
{
checkedListBox_modificar_permissions.SetItemChecked(i, true);
}
}
}
//Insert the new permissions (checked=true in the checkedList)
foreach (var item in checkedListBox_modificar_permissions.CheckedItems)
{
Permission permission = HandyClass.GetPermission(item.ToString(), db);
role.Permissions.Add(permission);
db.SaveChanges();
}
I get this error in the line db.SaveChanges();
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.
回答1:
The problem is that the collection role.Permissions
is not loaded before you make changes to it. This is because
It cant't be lazy loaded. To enable lazy loading, add the
virtual
modifier:public virtual ICollection<Permission> Permissions
It isn't loaded eagerly, which can be done by
Include
:from s in db.Roles.Include(r => r.Permissions) ...
So you should do either of these, or both. Eager loading is preferred, because it grabs the data in one query.
The exception isn't too clear. It refers to case where entities don't have primitive foreign key properties, only collections and references to objects. But this only applies to 1-n associations. In the classical Order-Orderline
association, Orderline
may have
public virtual Order Order { get; set; }
which makes this an independent association
and also
[ForeignKey("Order"]
public virtual int OrderId { get; set; }
which turns it into a foreign key association.
But in a many-to-many association the entities can't have these primitive properties, because the foreign keys are in the hidden junction table roles_permissions
. EF could give a more descriptive exception message here.
来源:https://stackoverflow.com/questions/21502829/how-to-update-a-many-to-many-relationship