在此上下文中启动了第二个操作

Posted

技术标签:

【中文标题】在此上下文中启动了第二个操作【英文标题】:A second operation started on this context 【发布时间】:2019-04-07 21:32:17 【问题描述】:

在我的控制器中,我在保存到 DB 的日期之后执行另一个 Void 函数。但有时它会显示此错误:

第二个操作在前一个上下文之前开始 异步操作完成。使用“等待”确保任何 异步操作在调用另一个方法之前已经完成 在这种情况下。不保证任何实例成员都是线程 安全。

...这是我的控制器的示例:

public ActionResult All(Chapter chapter)

    var x = db.Post.Where(p => p.PostID == chapter.PostID).FirstOrDefault();
    if (x == null)return View(chapter);

    counter++;

    db.Chapter.Add(chapter);
    db.SaveChangesAsync();                      

    savepost(chapter.PostID, counter);

    return RedirectToAction("Index");

这里是 Void 方法:

public void savepost(int id,int counter)

    var article = db.Post.Find(id);
    article.LastUpdate = DateTime.Now;
    article.ChapterCount = counter;

    db.Entry(article).State = EntityState.Modified;
    db.SaveChanges();

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

最短修复:

//db.SaveChangesAsync(); 
db.SaveChanges(); 

稍微好一点的选择:

public async Task<ActionResult> All(Chapter chapter)

   ....
   await db.SaveChangesAsync(); 
   ...

您没有等待对 SaveChangesAsync() 的调用,这意味着它将(可以)在单独的线程上分叉。然后它给你这个错误,一个 DbContext 不能在线程之间共享。

作为练习,您可以对 SavePost() 方法进行类似的更改:

使其成为async Task 方法 将 SaveChanges() 替换为 await db.SaveChangesAsync() 等待 SavePost() 的调用

【讨论】:

遇到这个问题 'ChapterID' 属性是对象关键信息的一部分,不能修改。 完全不相关,再问一个问题 - 并在那里提供相关代码。 作为一种解决方案,它可以工作,但是在我的控制器中,我使用 foreach 将多个模型添加到数据库中,因为 Chapter 的表 id 是标识并且由模型给出,所以我遇到了这个问题.. 你知道我是怎么做到的吗?可以为每个模型添加多模型,因为它是主键,所以重要的是在 DB 中获取下一个 Id 好吧,在我离开了我发布的操作结果之后,我建议你将 void 更改为异步任务,并将 db.save 更改为 SaveChangesAsync 它的工作原理,没问题..谢谢所有人都做得很好 当你使 SavePost 异步时,你必须等待它,你不能用你原来的非任务 All 动作来做到这一点......

以上是关于在此上下文中启动了第二个操作的主要内容,如果未能解决你的问题,请参考以下文章

UserManager 错误“在前一个操作完成之前在此上下文上启动了第二个操作”

UserManager 错误 - 在前一个异步操作完成之前在此上下文上启动了第二个操作

asp.net core 在前一个操作完成之前在此上下文上启动了第二个操作

EF 错误:在前一个异步操作完成之前在此上下文上启动了第二个操作

Entity Framework Core:在前一个操作完成之前在此上下文上启动了第二个操作

在前一个异步操作完成之前,在此上下文上启动了第二个操作。使用“等待”来确保