第二次调用同一个 DbContext 会引发错误“DbContext 已被释放”。

3

我想要做的事情

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

    person.Lastname = "Jameson";

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

出现问题的地方

以上保存方法调用了以下代码:

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;
        }
    }
}

var entry = context.Entry(source);这一行导致了这个错误:

无法完成操作,因为DbContext已被释放。

我看到类似问题的答案建议使用 .ToList()(或其他执行链接的方法),但是这样做不起作用,因为 Get 返回一个DTO对象。

一些背景

在保存时使用的 PersonManager,使用以下代码设置DbContext:

var context = new MyEntities();
this.PersonRepository = repositoryProvider.GetRepositoryByType<PersonRepository>(context);
< p > var context = new MyEntities(); 只是为了使其现在可用,这将被 DI 注入。

这又取决于以下内容:

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

    instance.SetContext(context);

    return (T)instance;
}

由于使用的是同一个PersonManager,实际上使用的是同一个PersonRepository (因此使用相同的上下文),所以我不明白为什么在第二次调用时它会被释放。


你的 Get 和 Save 都使用了 PersonRepository 吗? - Alexander Derck
@AlexanderDerck:正确,由运行它们的“PersonManager”提供。 - Spikee
1个回答

3
您没有提供创建上下文的背景,但我假设您是在一个方法中创建,可能是构造方法。您的上下文限定于该方法范围内,因此当方法调用结束时,GC可以自由地将其处理掉。我认为即使只有一次,它也能工作,这是因为您成功地在垃圾回收之前找到了它。
具有讽刺意味的是,您的问题发生在您还没有使用DI的情况下。简单地注入就足以解决问题。至少,您的上下文应该与PersonManager处于相同的级别。

没错,我正在使用构造函数注入。请查看我的有关依赖注入的更新。 - Spikee
垃圾回收器从不直接调用 .Dispose() 方法。垃圾回收器可能会调用终结器,而终结器可能会显式地调用 .Dispose() 方法,但在大多数情况下,垃圾回收器不会触发释放操作。 - Enigmativity
1
@Spikee:那是完全不同的问题,从技术上讲应该提出自己的问题,但可以简单地说,这归结于你如何处理添加操作。可能存在一些问题,很可能与其他代码中发生的事情有关(通过将实体添加到集合中隐式添加实体等)。 - Chris Pratt
1
刚刚测试了一下,我可以确认。如果我像Spikee那样从方法中返回一个上下文,我就可以获取一些实体。如果我让我的线程睡眠5秒钟等待一下,我就不能再使用这个上下文获取实体了,这表明它已经被释放了。 - Alexander Derck
完成依赖注入后,我取得了更进一步的进展。仍然存在一个问题,但这超出了本问题的范围(并且可能非常具体)。请参见此处:http://stackoverflow.com/questions/34291602/unable-to-save-because-of-another-entity-of-the-same-type-already-has-the-same - Spikee
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接