Entity Framework 6: Context Management Problem

Asked

Viewed 88 times

0

I have the object Agenda and create it as follows:

public class Program
{
    public static void Main(string[] args)
    {
        var clienteDAO = new ClienteDAO();
        var treinoDAO = new TreinoDAO();
        var agendaDAO = new AgendaDAO();

        var treino1 = treinoDAO.ObterTreino(1);
        var treino2 = treinoDAO.ObterTreino(2);

        var agenda = new Agenda();
        agenda.Data = new DateTime(2017,12,11);
        agenda.Horario = "14:00";
        agenda.Observacoes = "";
        agenda.Treinos.Add(treino1);
        agenda.Treinos.Add(treino2);

        agendaDAO.Cadastrar(agenda, 2);
    }
}

When registering, the EF error saying that there are multiple contexts managed the same object (in this case, the training object). This is because I used another context to search the workouts. So I try to 'untie' and add to the context again, but the problem persists:

public class AgendaDAO
{
    private PJContext _db = new PJContext();

    public void Cadastrar(Agenda agenda, int clienteId)
    {
        agenda.ClienteId = clienteId;

        foreach (var treino in agenda.Treinos)
        {
            _db.Entry(treino).State = EntityState.Detached;
            _db.Entry(treino).State = EntityState.Added;
        }

        _db.Set<Agenda>().Add(agenda);
        _db.SaveChanges();
    }
}

System.Invalidoperationexception: 'An Entity Object cannot be referenced by Multiple instances of Ientityctrackerhange.'

When I do "Detached" it does nothing, because I think only the other context that is watching it can do that. Is there any way to take it out of context?

  • You are Dispose in Your Context after You Consult?

  • Ah, I didn’t do it :|

  • Take the test if you will fix the problem and share with the community, if you clean up I answer the question.

  • Funny, I look for the object, stored in a variable after I disposed and return the same, but error saying that I can’t search for the object.

  • Is this object Iqueryable? As long as it is Iqueryable it will not be in memory and you will give Ispose before it is placed. Make the conversion using Tolist() and see if it resolves.

  • Vishe, I don’t know much about Iqueryable. I tried to remove List<Workout> from the Notebook for Iqueryable<Workout> and create a method to add workout and within that method convert Iqueryable to List. But the problem is that it gives error in mapping Fluent api as it does not accept Iqueryable.

  • After searching for the object, I untied it and returned, it worked. But I do not know if this is the best way to do.

  • 1

    The context is observing its entities in search of changes. When you instance a new Dbcontext it ignores these changes (because they are in another Dbcontext). Working in EF with multiple Dbcontext ends up being complicated. Perhaps the best solution is to use Singleton Pattern.

Show 4 more comments

1 answer

2


You need to do the Dispose connection with the bank. When you don’t, your first query causes the Entity Framework to track that object (Using the .AsNoTracking() help it not happen). Then when you tried to add it, you were doing the track of that object again, then did it twice, it can’t happen.

The problem with Iqueryable is that it builds a query expression tree in the database, while you do not call the .Execute() or make the conversion, he did not consult the values.

You were making the Dispose (action to release the connection to the bank) before the Iqueryable actually runs and bring the result of the query, just when you try to return it, it will see that the connection to the bank has been released and the error happens.

Browser other questions tagged

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