简体   繁体   中英

Second call to same DbContext causes error 'DbContext has been disposed'

What I'm trying to do

public void SomeTestMethod(){
    var person = this.PersonManager.Get(new Guid("someguid")); 

    person.Lastname = "Jameson";

    this.PersonManager.Save(person); // This goes wrong
}

Where it goes wrong

The above save method calls this code:

protected void Add<T>(T source, MyEntities context, bool isNew) where T : class
{
    if (isNew)
    {
        context.Set<T>().Add(source);
    }
    else
    {
        var entry = context.Entry(source);
        if (entry.State == EntityState.Detached)
        {
            context.Set<T>().Attach(source);

            entry.State = EntityState.Modified;
        }
    }
}

The var entry = context.Entry(source); line is the one causing this error:

The operation cannot be completed because the DbContext has been disposed.

I've seen answers to similar questions that suggested to use .ToList() (or something else to execute the link), but that has happened, because the Get returns a DTO object.

Some background

The PersonManager used in save, uses this to set the DbContext:

var context = new MyEntities();
this.PersonRepository = repositoryProvider.GetRepositoryByType<PersonRepository>(context);

The var context = new MyEntities(); is just to get it working now, this will be DI injected.

Which in turn depends on this:

public T GetRepositoryByType<T>(MyEntities context) where T : IContextDependent
{
    var instance = this.Repositories.SingleOrDefault(x => x is T);

    instance.SetContext(context);

    return (T)instance;
}

As the same PersonManager is used, de facto the same PersonRepository is used (and as a result the same context) , so I don't see why it would be disposed on the second call.

You haven't given the context of where you're creating your context, but I'm assuming it's in a method, perhaps the constructor. Your context is scoped to that method, so the GC is free to dispose of it when the method call ends. I think the fact that it works at all, even just once, is that you're managing to hit it before it's garbage collected.

Ironically, your issue is occurring because you're not using DI yet. Simply injecting it would be enough likely to solve the issue. At the very least, your context should be scoped at the same level as PersonManager .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM