Fede Lerner
Fede Lerner

Reputation: 477

Remove entity with related entities in EntityFramework

I have the following code:

[HttpPost]
public ActionResult Eliminar(Usuario usuario)
{
        db.Usuarios.Attach(usuario);
        usuario.Transacciones.ToList().ForEach(t => db.Transacciones.Remove(t));
        usuario.Eventos.ToList().ForEach(e => db.Eventos.Remove(e));
        db.Usuarios.Remove(usuario);
        db.SaveChanges();
        return RedirectToAction("Index");
}

I can't make it work. I know that to delete an entity you first have to attach it, but it isn't working for an entity that has relations. I've also tried to do a foreach loop, and attaching each Transaccion and Evento entities before removing them, but it doesn't work neither.

This is the error the InnerException contains:

System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK_TR_US". The conflict occurred in database "bd_dm", table "dbo.Transacciones", column 'idUsuario'. The statement has been terminated.

I know what that means, but I don't know how to make the code work. I need to remove first all the Transacciones and Eventos related to the Usuario, to be able to remove the Usuario.

Upvotes: 3

Views: 5125

Answers (2)

TheDarkTrumpet
TheDarkTrumpet

Reputation: 96

This probably won't help you , but may help those who see this (like I did when researching this problem).

Doing the foreach/remove combination you're doing above isn't necessary if 'cascade on delete' is setup on the database. There are a few ways to do this, but this chapter in 'Programming Entity Framework: Code First' https://www.safaribooksonline.com/library/view/programming-entity-framework/9781449317867/ch04s04.html explains it very well.

In your case above:

usuario.Transacciones

usuario.Eventos

Just go into that association's class, and on the reverse key (likely in this case, public virtual Usuarios;, in the associations' class) add the decorator [Required], which will change the foreign key such that it has cascade on delete.

If you don't do this, those associations will be set to null instead of being removed.

Upvotes: 1

Fede Lerner
Fede Lerner

Reputation: 477

After a lot of debugging (in a remote server) I found out what the problem was. The Usuario usuario data is passed to the Eliminar method correctly, but the related objects are not. So I have to load them before being able to remove them, and then remove the Usuario object.

This is my final code:

[HttpPost]
public ActionResult Eliminar(Usuario usuario)
{
    db.Usuarios.Attach(usuario);
    db.Entry(usuario).Collection("Transacciones").Load();
    db.Entry(usuario).Collection("Eventos").Load();

    usuario.Transacciones.ToList().ForEach(t => db.Transacciones.Remove(t));
    usuario.Eventos.ToList().ForEach(e => db.Eventos.Remove(e));
    db.Usuarios.Remove(usuario);
    db.SaveChanges();

    return RedirectToAction("Index");
}

Upvotes: 3

Related Questions