Puede actualizar un muchos-a-muchos relación de esta manera (como un ejemplo que da el usuario 3 el papel 5):
using (var context = new MyObjectContext())
{
var user = context.Users.Single(u => u.UserId == 3);
var role = context.Roles.Single(r => r.RoleId == 5);
user.Roles.Add(role);
context.SaveChanges();
}
Si la colección User.Roles
se declara como virtual
la La línea user.Roles.Add(role);
activará la carga diferida, lo que significa que todos los roles de para el usuario se cargan primero de la base de datos antes de agregar el nuevo rol.
Esto es, de hecho, preocupante porque no es necesario cargar toda la colección Roles
para agregar un nuevo rol al usuario.
Pero esto no significa que tenga que eliminar la palabra clave virtual
y abandonar por completo la carga diferida. Usted sólo puede desactivar la carga diferida en esta situación específica:
using (var context = new MyObjectContext())
{
context.ContextOptions.LazyLoadingEnabled = false;
var user = context.Users.Single(u => u.UserId == 3);
var role = context.Roles.Single(r => r.RoleId == 5);
user.Roles = new List<Role>(); // necessary, if you are using POCOs
user.Roles.Add(role);
context.SaveChanges();
}
Editar
Si desea actualizar toda la colección de papeles de un usuario preferiría para cargar los papeles originales con carga ansiosa (= Include
). Es necesario esta lista de todos modos para eliminar posiblemente algunos papeles, por lo que no es necesario esperar hasta que la carga diferida de ellos obtiene a partir de la base de datos:
var newRolsIds = new List<int> { 1, 2, 5 };
using (var context = new MyObjectContext())
{
var user = context.Users.Include("Roles")
.Single(u => u.UserId == 3);
// loads user with roles, for example role 3 and 5
var newRoles = context.Roles
.Where(r => newRolsIds.Contains(r.RoleId))
.ToList();
user.Roles.Clear();
foreach (var newRole in newRoles)
user.Roles.Add(newRole);
context.SaveChanges();
}
En lugar de cargar las nuevas funciones de la base de datos también puede adjuntar ellos desde usted sabe en el ejemplo el valor de la propiedad clave. También puede eliminar exactamente las funciones que faltan en lugar de borrar toda la colección y en lugar de volver a agregar las funciones existentes:
var newRolsIds = new List<int> { 1, 2, 5 };
using (var context = new MyObjectContext())
{
var user = context.Users.Include("Roles")
.Single(u => u.UserId == 3);
// loads user with roles, for example role 3 and 5
foreach (var role in user.Roles.ToList())
{
// Remove the roles which are not in the list of new roles
if (!newRoleIds.Contains(role.RoleId))
user.Roles.Remove(role);
// Removes role 3 in the example
}
foreach (var newRoleId in newRoleIds)
{
// Add the roles which are not in the list of user's roles
if (!user.Roles.Any(r => r.RoleId == newRoleId))
{
var newRole = new Role { RoleId = newRoleId };
context.Roles.Attach(newRole);
user.Roles.Add(newRole);
}
// Adds roles 1 and 2 in the example
}
// The roles which the user was already in (role 5 in the example)
// have neither been removed nor added.
context.SaveChanges();
}
th Slauma. Entendí el caso en el que deseo agregar un nuevo Rol al usuario de la colección. Roles. Lo que no puedo entender es el caso general en el que tengo que manipular un conjunto de Roles. Por ejemplo: user.Roles contiene 3,5 roles; luego, elijo actualizar user.Roles para que contenga 1,2,5 (tengo que eliminar 3 y tengo que agregar 1,2 en user.Roles). ¿Funciona de la misma manera? – frabiacca
@frabiacca: ver mi edición. – Slauma
¡Lo intenté ... y funciona! :) thx tanto slauma – frabiacca