已经处理了ObjectContext实例 - 这个线程是否安全?

时间:2018-03-14 15:51:27

标签: c# multithreading entity-framework

我有一个System.Threading.Timer的集合,它在webapp的后台运行,定期从数据库中检索数据以更新缓存。

偶尔(不经常),对DB的调用将失败并出现错误,例如" ObjectContext实例已被处理,不能再用于需要连接的操作"。

它似乎有时会被另一个线程处理掉,但是当每个计时器运行时,它会创建一个全新的DbContext,所以我不确定这是怎么回事。

我使用StructureMap创建一个嵌套容器,以便它独立运行,并且我已经验证它确实为每个计时器创建了一个新的DbContext。

var a = new A();
var b = new B();

var timer1 = new Timer(x => a.Update(container), null, TimeSpan.Zero, TimeSpan.FromMinutes(60));
var timer2 = new Timer(x => b.Update(container), null, TimeSpan.Zero, TimeSpan.FromMinutes(60));

public class A 
{
    public void Update(IContainer container)
    { 
        using (var nestedContainer = container.GetNestedContainer()) {
            // This will create a new DbContext and will be disposed 
            // when the nested container is disposed
            var repository = nestedContainer.GetInstance<IRepositoryA>();

            // Sometimes fails here when it's accessing the DbContext
            repository.GetStuff();
        }
    }
}

public class B
{
    public void Update(IContainer container)
    { 
        using (var nestedContainer = container.GetNestedContainer()) {
            var repository = nestedContainer.GetInstance<IRepositoryB>();

            repository.GetStuff();
        }
    }
}

这是StructureMap配置。因此,无论何时创建存储库,它都将创建一个新工厂,从而创建一个新的MyDbContext。

For<IDbContextFactory<MyDbContext>>().HybridHttpOrThreadLocalScoped()
    .Use(() => new DbContextFactory());

1 个答案:

答案 0 :(得分:0)

事实证明这是由[END] StructureMap插件引起的,该插件在本地线程处理嵌套容器时处理了DbContext,因此其他线程无法再使用它。删除它并更改我的StructureMap配置以使用嵌套容器来解决HTTP请求的生命周期。