Deletion of related data - Entity Framework and C#

Asked

Viewed 744 times

5

Hello,

Using the same structure that I have been presenting here for some time, I come to ask for help now to delete the related data. Follows 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 exclude an artist.

When I delete an error message is shown.

The DELETE statement conflicted with the REFERENCE Constraint "Fk_dbo.Artista_dbo.Addresse_addresse_addresse_addressed". The Conflict occurred in database "showfacil", table "dbo. Artist", column 'Addresse_addressed'. The statement has been terminated.

follows 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();
    }
}
  • The DELETE CASCADE is enabled for tables? If not, it will be necessary to remove the tables below and then remove the tables above.

  • Delete Cascade is not enabled and I tried to delete the address and then the artist and also the opposite, the artist and then the address, in both cases gave the same error..

  • When you delete the address first, I tried to put the artist.endereco = null

2 answers

2

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

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

It will return null if it cannot find an item. The point is that first it will look in 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 alteration/deletion. Effecting the search for Find my problem has been solved.

Another point is "Savechanges". This is a hint. Run it only at the end of all iterations.

Entity opens a transaction for you to execute all "Remove" and then "Commit" these changes, which would be our "Savechanges". That is, keep only the last, which is inside the method "Remove":

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

The rest can be removed.

0

Try to change 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 don’t understand here is the code artista.Endereco = null;, as far as I know when you delete the context already removes that data then you don’t need to do Endereco = null;, Another thing is Asnotracking. this method makes the recovered Addresses not already controlled by the context so when you are going to save the Address back to the database you must attach it and correctly set state of the Address so that EF.

But details here and here

Browser other questions tagged

You are not signed in. Login or sign up in order to post.