Deletion of related data - Entity Framework and C #

5

Hello,

Using the same structure I've been presenting here for some time now, I've come to you for help now to delete the related data. Follow the entities ..

public class Artista
{
    public int ArtistaId { get; set; }
    public string Nome { get; set; }
    public string Email { get; set; }
    public string Site { get; set; }
    public string Descricao { get; set; }
    public virtual Endereco Endereco { get; set; }
    public DateTime DataCadastro { get; set; }
    public DateTime DataAtualizacao { get; set; }
    public virtual ICollection<ArtistaCategoria> ArtistaCategoria { get; set; }
}

public class Categoria
{
    public Categoria()
    {
    }

    public int CategoriaId { get; set; }
    public string Nome { get; set; }
    public virtual ICollection<ArtistaCategoria> ArtistaCategoria { get; set; }
}

public class ArtistaCategoria
{
    public int ArtistaCategoriaId { get; set; }
    public int ArtistaId { get; set; }
    public int CategoriaId { get; set; }
    public virtual Artista Artista { get; set; }
    public virtual Categoria Categoria { get; set; }
}

public class Endereco
{
    public Endereco()
    {
        Municipio = new Municipio();
    }
    public int EnderecoId { get; set; }
    public string Logradouro { get; set; }
    public string Numero { get; set; }
    public string Bairro { get; set; }
    public string Cep { get; set; }
    public int MunicipioId { get; set; }
    public virtual Municipio Municipio { get; set; }
}

public class Municipio
{
    public Municipio()
    {
    }

    public int MunicipioId { get; set; }
    public string Nome { get; set; }
    public string Cep { get; set; }
}

In this case, how to delete an artist.

When I delete, an error message is displayed.

  

The DELETE statement conflicted with the REFERENCE constraint   "FK_dbo.Device.Endereco_EnderecoId". The conflict   occurred in database "showfacil", table "dbo.Artista", column   'Endereco_EnderecoId'. The statement has been terminated.

follow the code:

public void Remove(Artista artista)
{
    var a = Db.Artistas.First(x => x.ArtistaId == artista.ArtistaId);

    Db.Artistas.Attach(a);

    RemoverTelefones(a);
    RemoverEndereco(a);
    RemoverCategorias(a);

    Db.Set<Artista>().Remove(a);
    Db.SaveChanges();
}


private void RemoverTelefones(Artista artista)
{
    // Telefones Originais
    var telefonesOriginais = Db.TelefoneArtista.AsNoTracking().Where(at => at.ArtistaId == artista.ArtistaId).ToList();

    if (artista.ArtistaTelefones != null)
    {
        // Telefones Excluídos
        foreach (var telefoneOriginal in telefonesOriginais)
        {
            var telefoneExcluido = Db.TelefoneArtista.Single(rt => rt.TelefoneArtistaId == telefoneOriginal.TelefoneArtistaId);
            Db.TelefoneArtista.Remove(telefoneExcluido);
            Db.SaveChanges();
        }
    }
}

private void RemoverCategorias(Artista artista)
{
    var categorias = Db.ArtistaCategoria.AsNoTracking().Where(at => at.ArtistaId == artista.ArtistaId).ToList();

    foreach (var categoria in categorias)
    {
        var catExcluida = Db.ArtistaCategoria.Single(rt => rt.ArtistaCategoriaId == categoria.ArtistaCategoriaId);
        Db.ArtistaCategoria.Remove(catExcluida);
        Db.SaveChanges();
    }
}

private void RemoverEndereco(Artista artista)
{
    var enderecos = Db.Enderecos.AsNoTracking().Where(at => at.EnderecoId == artista.Endereco.EnderecoId).ToList();
    artista.Endereco = null;
    foreach (var endereco in enderecos)
    {
        var endExcluido = Db.Enderecos.Single(rt => rt.EnderecoId == endereco.EnderecoId);
        Db.Enderecos.Remove(endExcluido);
        Db.SaveChanges();
    }
}
    
asked by anonymous 13.02.2016 / 16:06

2 answers

2

Alexandre, instead of using "Single", try using "Find". It would look like this:

var endExcluido = Db.Enderecos.Find(endereco.EnderecoId);

It will return null if it can not find an item. The point is that it will first look at the context before going to the database, which can be an important efficiency factor. I had a problem very similar to yours and it was that the object was not in context for change / delete. Doing the Find search for my problem has been resolved.

Another point is the "SaveChanges". That's a tip. Run it only at the end of all iterations.

Entity opens a transaction for you to perform all "Remove" and finally to "commit" these changes, which would be our "SaveChanges". That is, just keep the last one, which is inside the "Remove" method:

Db.Set<Artista>().Remove(a);
Db.SaveChanges();

The rest can be removed.

    
16.02.2016 / 16:36
0

Try changing your method as follows.

public void Remove(Artista artista)
{
    var artistas = Db.Artistas.First(x => x.ArtistaId == artista.ArtistaId);


    RemoverTelefones(artistas);
    RemoverEndereco(artistas);
    RemoverCategorias(artistas);

    Db.Artista.Remove(artistas);
    Db.SaveChanges();
}


private void RemoverTelefones(Artista artista)
{
    // Telefones Originais
    var telefonesOriginais = Db.TelefoneArtista.Where(at => at.ArtistaId == artista.ArtistaId);
    Db.TelefoneArtista.RemoveRange(telefonesOriginais);
    Db.SaveChanges();       
}

private void RemoverCategorias(Artista artista)
{
    var categorias = Db.ArtistaCategoria.Where(at => at.ArtistaId == artista.ArtistaId);
    Db.ArtistaCategoria.RemoveRange(categorias);
    Db.SaveChanges();
}

private void RemoverEndereco(Artista artista)
{
    var enderecos = Db.Enderecos.AsNoTracking().Where(at => at.EnderecoId == artista.Endereco.EnderecoId).ToList();
    Db.Enderecos.RemoveRange(enderecos);
    Db.SaveChanges();    
}

One thing I did not understand here is the code artista.Endereco = null; , so far as I know when you delete it the context already removes this data so you do not need to Endereco = null; , another thing is AsNoTracking. this method causes the retrieved Addresses to not be controlled by the context so when you are going to save the Address back to the database you must attach it and correctly define the Address State for that EF.

More details here and here

    
16.02.2016 / 17:01