Array
(
)

Problemas com Relacionamento Many to Many no Entity Framework 5.0.0

Kassio Silva
   - 18 out 2013

Olá Pessoal, tudo bem?
Estou desenvolvendo uma aplicação simples com C#, utilizando o Entity Framework v5.0.
Minha dúvida é a seguinte, criei duas classes, onde uma é EmpresaFornecedora e outra é Contato.
Fiz um mapeamento Muitos pra Muitos.
Só que no unit test com NUnit eu consigo inserir normalmente a empresa e o contato, porém quando vou removê-los no TearDown dá o Erro " System.InvalidOperationException : Não é permitido adicionar uma relação com uma entidade que está no estado Deleted."
Se eu comentar a linha em que estou relacionando o contato com a empresaFornecedora, funciona normal.
Como que faço para excluir junto com o contato e empresaFornecedora, o registro da tabela de relacionamento EmpresaFornecedora_Contato ?
Segue meus códigos:
#Códigopublic class Context : DbContext
{
public DbSet<EmpresaFornecedora> EmpresasFornecedoras { get; set; }
public DbSet<Endereco> Enderecos { get; set; }
public DbSet<Contato> Contatos { get; set; }
public DbSet<UsuarioSistema> UsuarioSistemas { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<EmpresaCliente>().HasMany(c => c.Contatos).WithMany(e => e.EmpresasClientes)
.Map(m =>
{
m.MapLeftKey("EmpresaClienteId");
m.MapRightKey("ContatoId");
m.ToTable("Contato_EmpresaCliente");
});
modelBuilder.Entity<EmpresaFornecedora>().HasMany(c => c.Contatos).WithMany(e => e.EmpresasFornecedoras)
.Map(m =>
{
m.MapLeftKey("EmpresaFornecedoraId");
m.MapRightKey("ContatoId");
m.ToTable("Contato_EmpresaFornecedora");
});
modelBuilder.Entity<Funcionario>().HasMany(c => c.Contatos).WithMany(f => f.Funcionarios)
.Map(m =>
{
m.MapLeftKey("FuncionarioId");
m.MapRightKey("ContatoId");
m.ToTable("Contato_Funcionario");
});
modelBuilder.Entity<Tecnico>().HasMany(c => c.Contatos).WithMany(t => t.Tecnicos)
.Map(m =>
{
m.MapLeftKey("TecnicoId");
m.MapRightKey("ContatoId");
m.ToTable("Contato_Tecnico");
});
base.OnModelCreating(modelBuilder);
}
}


#Código
public abstract class EmpresaFornecedora : BaseEntidade
{
[Required(ErrorMessage = "O preenchimento do campo NOME é necessário.")]
[MaxLength(100, ErrorMessage = "O tamanho máximo é de 100 caractéres.")]
public string RazaoSocial { get; set; }
[Required(ErrorMessage = "O preenchimento do campo NOME FANTASIA é necessário.")]
[MaxLength(100, ErrorMessage = "O tamanho máximo é de 100 caractéres.")]
public string NomeFantasia { get; set; }
[Required(ErrorMessage = "O preenchimento do campo CNPJ é necessário.")]
[MaxLength(20, ErrorMessage = "O tamanho máximo é de 20 caractéres.")]
[PropriedadeComparavel]
public string Cnpj { get; set; }
[Required(ErrorMessage = "O preenchimento do campo IE é necessário.")]
[MaxLength(20, ErrorMessage = "O tamanho máximo é de 20 caractéres.")]
public string Ie { get; set; }
public virtual Endereco Endereco { get; set; }
public virtual ICollection<Contato> Contatos { get; set; }
public virtual UsuarioSistema UsuarioSistema { get; set; }
}

#Códigopublic class Contato : BaseEntidade
{
[Required(ErrorMessage = "O preenchimento do campo DESCRIÇÃO é necessário.")]
[MaxLength(80, ErrorMessage = "O tamanho máximo é de 80 caractéres.")]
public string Descricao { get; set; }
[Required(ErrorMessage = "O preenchimento do campo TIPO é necessário.")]
public virtual TipoContato TipoContato { get; set; }
public virtual ICollection<EmpresaFornecedora> EmpresasFornecedoras { get; set; }
}

#Código public abstract class BaseNegocio<T> where T : class
{
protected Context Context;
protected BaseNegocio()
{
Context = Repositorio.Instanciar();
}
public virtual void Inserir(T objeto)
{
try
{
Context.Set<T>().Add(objeto);
Context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
string msgErro = string.Empty;
var erros = Context.GetValidationErrors();
msgErro = erros.SelectMany(erro => erro.ValidationErrors).Aggregate(msgErro, (current, detalheErro) => current + (detalheErro.ErrorMessage + "\n"));
Context.Entry(objeto).State = EntityState.Detached;
throw new InvalidOperationException(msgErro);
}
}
public virtual void Alterar(T objeto)
{
try
{
Context.Entry(objeto).State = EntityState.Modified;
Context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
string msgErro = string.Empty;
var erros = Context.GetValidationErrors();
msgErro = erros.SelectMany(erro => erro.ValidationErrors).Aggregate(msgErro, (current, detalheErro) => current + (detalheErro.ErrorMessage + "\n"));
Context.Entry(objeto).State = EntityState.Detached;
throw new InvalidOperationException(msgErro);
}
}
public virtual void Excluir(int id)
{
var objeto = Context.Set<T>().Find(id);
if (objeto == null)
throw new InvalidOperationException("Não existe um registro com a(s) característica(s) informada(s).");
try
{
Context.Set<T>().Remove(objeto);
Context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
string msgErro = string.Empty;
var erros = Context.GetValidationErrors();
msgErro = erros.SelectMany(erro => erro.ValidationErrors).Aggregate(msgErro, (current, detalheErro) => current + (detalheErro.ErrorMessage + "\n"));
Context.Entry(objeto).State = EntityState.Detached;
throw new InvalidOperationException(msgErro);
}
}
public virtual List<T> RetornarTodos()
{
var objetos = Context.Set<T>();
return objetos.ToList();
}
public virtual T RetornarPorId(int id)
{
var objeto = Context.Set<T>().Find(id);
if (objeto == null)
return null;
return objeto;
}
}


#Código public class EmpresaFornecedoraNegocio : BaseNegocio<EmpresaFornecedora>
{
}

#Código[TestFixture]
public class EmpresaFornecedoraNegocioTeste : IBaseTeste
{
private EmpresaFornecedoraNegocio empresaFornecedoraNegocio;
private EnderecoNegocio enderecoNegocio;
private ContatoNegocio contatoNegocio;
private UsuarioSistemaNegocio usuarioSistemaNegocio;
private EmpresaFornecedora empresaFornecedora1, empresaFornecedora2;
[TestFixtureSetUp]
public void InicializarClasseDeTestes()
{
//Instanciando repositório de empresas fornecedoras
empresaFornecedoraNegocio = new EmpresaFornecedoraNegocio();
//Instanciando repositório de endereços
enderecoNegocio = new EnderecoNegocio();
//Instanciando repositório de contatos
contatoNegocio = new ContatoNegocio();
//Instanciando repositório de usuários sistema
usuarioSistemaNegocio = new UsuarioSistemaNegocio();
//Ambiente para os demais métodos de testes
var endereco1 = new Endereco()
{
Logradouro = "Rua 11",
Numero = "0022",
Bairro = "Centro",
Cidade = "Guaíra",
Cep = "14790000",
Estado = "SP",
Pais = "Brasil"
};
var endereco2 = new Endereco()
{
Logradouro = "Rua 45",
Numero = "0062",
Bairro = "Centro",
Cidade = "Barretos",
Cep = "15688009",
Estado = "SP",
Pais = "Brasil"
};
//enderecoNegocio.Inserir(endereco1);
//enderecoNegocio.Inserir(endereco2);
var contato1 = new Contato()
{
Descricao = "email@email.com.br",
TipoContato = TipoContato.EMAIL
};
var contato2 = new Contato()
{
Descricao = "17993202344",
TipoContato = TipoContato.CELULAR
};

//contatoNegocio.Inserir(contato1);
//contatoNegocio.Inserir(contato2);
var usuarioSistema1 = new UsuarioSistema()
{
Usuario = "jose.s",
Senha = "123321",
Nivel = 1
};
var usuarioSistema2 = new UsuarioSistema()
{
Usuario = "joao.a",
Senha = "654321",
Nivel = 1
};
//usuarioSistemaNegocio.Inserir(usuarioSistema1);
//usuarioSistemaNegocio.Inserir(usuarioSistema2);
empresaFornecedora1 = new EmpresaFornecedora
{
RazaoSocial = "Intersoft Soluções LTDA",
NomeFantasia = "Intersoft Soluções",
Cnpj = "213123123123",
Ie = "123123123123",
Endereco = endereco1,
UsuarioSistema = usuarioSistema1,
Contatos = new Collection<Contato> {contato1}
};
empresaFornecedora2 = new EmpresaFornecedora
{
RazaoSocial = "Softnet Soluções LTDA",
NomeFantasia = "Softnet Soluções",
Cnpj = "8282378387",
Ie = "12312313009",
Endereco = endereco2,
UsuarioSistema = usuarioSistema2,
Contatos = new Collection<Contato> {contato1},
};
}
[TearDown]
public void LimparCenarioDeTestes()
{
var retornoEmpresa = empresaFornecedoraNegocio.RetornarTodos();
var retornoContato = contatoNegocio.RetornarTodos();
var retornoEndereco = enderecoNegocio.RetornarTodos();
var retornoUsuario = usuarioSistemaNegocio.RetornarTodos();

//Exluindo EmpresasFornecedoras inseridos no decorrer dos testes
if (retornoEmpresa.Any())
{
foreach (var empresa in retornoEmpresa)
{
empresaFornecedoraNegocio.Excluir(empresa.Id);
}
}
//Exluindo Usuários inseridos no decorrer dos testes
if (retornoUsuario.Any())
{
foreach (var usuario in retornoUsuario)
{
usuarioSistemaNegocio.Excluir(usuario.Id);
}
}
//Exluindo Contatos inseridos no decorrer dos testes
if (retornoContato.Any())
{
foreach (var contato in retornoContato)
{
contatoNegocio.Excluir(contato.Id);
}
}
//Exluindo Endereços inseridos no decorrer dos testes
if (retornoEndereco.Any())
{
foreach (var endereco in retornoEndereco)
{
enderecoNegocio.Excluir(endereco.Id);
}
}
}
[Test]
public void PodeInserirTeste()
{
//Ação
empresaFornecedoraNegocio.Inserir(empresaFornecedora1);
//Assertivas
var retorno = empresaFornecedoraNegocio.RetornarPorId(empresaFornecedora1.Id);
Assert.IsNotNull(empresaFornecedora1);
Assert.IsNotNull(retorno);
Assert.AreEqual(retorno.Id, empresaFornecedora1.Id);
}
}