更新实体框架中的现有EntityCollection

时间:2011-08-29 20:02:21

标签: .net entity-framework repository

我正在尝试解决EF中的问题以更新我的实体中的集合:

[TestMethod]
public void DeveEditarUsuarioNoRepositorio()
{
    Usuario usuario = _usuarioRepository.GetById(1);

    usuario.Nome = "Samla Peidorreira";
    usuario.Email = "samlapeidanascalca@samlapeidanascalca.com";
    usuario.DataNascimento = new DateTime(1988, 11, 19, 4, 23, 54, 0);
    usuario.Sexo = (Sexo)Convert.ToByte(Sexo.Masculino);
    usuario.Telefone = null;
    usuario.Credencial.Status = (Status)Convert.ToByte(Status.Ativo);

    //That's the collection I want to update
    usuario.Credencial.Perfis = new List<Perfil>() { new Perfil() { Nome = "Fotografos", DataEdicao = new DateTime(1996, 2, 1, 12, 15, 42, 27), Deletado = true, Status = false, Tipo = 3 } };

    usuario.Credencial.NomeUsuario = "samlapeidanascalca";
    usuario.Credencial.Senha = "samlacagona";

    _usuarioRepository.Edit(usuario);

    _context.SaveChanges();

    Usuario usuarioEditado = _usuarioRepository.GetById(1);

    Assert.AreEqual("Samla Peidorreira", usuarioEditado.Nome);
    Assert.AreEqual("samlapeidanascalca@samlapeidanascalca.com", usuarioEditado.Email);
    Assert.AreEqual(new DateTime(1988, 11, 19, 4, 23, 54, 0), usuarioEditado.DataNascimento);
    Assert.AreEqual(Sexo.Masculino, usuarioEditado.Sexo);
    Assert.AreEqual(null, usuarioEditado.Telefone);
    Assert.AreEqual(Status.Ativo, usuarioEditado.Credencial.Status);
    Assert.AreEqual(1, usuarioEditado.Credencial.Perfis.Count);
    Assert.AreEqual(5, usuarioEditado.Credencial.Perfis[0].Id);
    Assert.AreEqual("samlapeidanascalca", usuarioEditado.Credencial.NomeUsuario);
    Assert.AreEqual("samlacagona", usuarioEditado.Credencial.Senha);
}

当我为新List设置Perfis属性时,它不会替换属性中的值,它会在该属性的实际List中添加新List的值。 WTF为什么会这样?

我要解决的问题是在我的实体中执行此操作:

public class Credencial : Entity
{
    private IList<Perfil> _perfis;

    public Credencial()
    {
        Status = Status.Inativo;
    }

    public virtual Usuario Usuario { get; set; }

    public virtual IList<Perfil> Perfis
    {
        get { return _perfis ?? (_perfis = new List<Perfil>()); }
        set { Perfis.Clear(); _perfis = value; }
    }

    public virtual Status Status { get; set; }
    public byte StatusId
    {
        get { return (byte)Status; }
        set { Status = (Status)value; }
    }
    public string NomeUsuario { get; set; }

    public string Senha { get; set; }
}

Perfis财产中查看我的 SET {} 。即使我想设置Perfis属性,也会这样做,它将清除列表并添加带有新Itens的新列表。

我做错了什么?没有人谈论这个解决方案。

1 个答案:

答案 0 :(得分:6)

确定。现在我明白你的问题。我以为你想要更新关系,但你想要替换它们并仍然保留旧对象。我希望UsuarioPerfil处于多对多的关系中,不是吗?

如果您只替换列表,则旧值仍然存在。 EF将不会删除它们,因为替换集合deoes不会影响它们,但是如果您在列表中调用clear,则删除当前Usuario和所有已加载Perfil之间的关系(它将从结点中删除记录) SaveChanges期间的表格。

我认为您不应该清除实体的setter中的列表。您甚至不应该允许更改集合。您应该在测试逻辑中调用clear,然后添加新的Perfil

usuario.Credencial.Perfis.Clear();
usuario.Credencial.Perfis.Add(new Perfil { ... });

原因是EF有时不喜欢你操纵导航属性的集合,它会触发无法分配初始化集合的异常。