具有实体框架的具有多个线程的单一上下文

Posted

技术标签:

【中文标题】具有实体框架的具有多个线程的单一上下文【英文标题】:Single context with many threads with Entity Framework 【发布时间】:2014-12-31 18:54:59 【问题描述】:

我有以下:

           await Task.WhenAll(
                 Task.Run(() => HandleJob("one"),
                 Task.Run(() => HandleJob("two"),
                 Task.Run(() => HandleJob("three"));

HandleJob 在哪里:

       private async Task HandleJob(string param) 
              using (var db = new DbContext()) 
                     _numberService = new NumberService(db);
                     _numberService.DoThis(param);
              
       

而 NumberService 是这样的:

    public class NumberService 

           private readonly DbContext db;

           private CommService _commService;

           public NumberService(DbContext db) 
              this.db = db;
              _commService = new CommService(db);
           


           public void DoThis(string param)
              _commService.DoThat(param);   
           

     

CommService 是这样的:

     public class CommService 

           private readonly DbContext db;

           public CommService(DbContext db) 
              this.db = db;
           

           public void DoThat(string param)
              db.Things.Add(param);
              db.SaveChanges();
           

     

我遇到了一个问题,当我尝试运行它时看到以下内容:

System.InvalidOperationException 类型的异常 发生在 EntityFramework.dll 但未在用户代码中处理 上下文 在创建模型时不能使用。这个例外可能是 如果在 OnModelCreating 方法中使用了上下文,或者如果 同一个上下文实例被多个线程访问 同时。请注意,DbContext 和相关的实例成员 不保证类是线程安全的。

我做错了什么?我认为通过为每个线程使用一个新的dbContext,我会没事的。

【问题讨论】:

对我来说似乎很好。我以前见过这个错误;它基本上可以表示各种各样的东西。在发生这种情况的地方发布整个调用堆栈。在 await 关键字之前试试这个:using (var dbCOntext = new DbContext()) dbCOntext.Database.Initialize(force: false); 这可能不是线程问题,您可能在该新上下文中执行代码,而该上下文尚不存在或仍在创建中。 db.Things.Add(param);是错误的,因为 param 是一个字符串,而不是 Thing 的实例。然后它继续抛出一个没有处理的异常 @TienDinh 这只是一个语法错误 - 我在这里简化代码。 回头看你的代码,我可以看到很多语法错误。我怀疑您的问题代码是否包含在内。 【参考方案1】:

我是个白痴。这是因为我在 async 方法之外定义了_numberService,所以每次异步使用都为其他使用重写了上下文。多哈。

【讨论】:

以上是关于具有实体框架的具有多个线程的单一上下文的主要内容,如果未能解决你的问题,请参考以下文章

无法生成显式迁移 - 具有多个上下文/配置的实体框架 6.1.3

具有实体框架的动态多数据库上下文

如何在具有存储库模式的实体框架中伪造 DbContext.Entry 方法

将 DbContext 拆分为具有重叠 DbSet 的多个上下文

具有实体框架 6 的 ObjectContext 在现有相关实体上插入重复项

实体框架分离实体和相关实体消失