【问题标题】:Parallel.ForEach Error showing dbcontext显示 dbcontext 的 Parallel.ForEach 错误
【发布时间】:2014-12-29 18:39:40
【问题描述】:

此方法 - doDayBegin(item.BranchId) 需要很长时间才能执行。所以我使用 Parallel.ForEach 并行执行它。当我使用正常的 foreach 循环时,它工作正常,但是当我使用 Parallel.ForEach 时,它显示此错误
在创建模型时不能使用上下文 Parallel.ForEach

 public ActionResult Edit([DataSourceRequest] DataSourceRequest request)
        {
            try
            {
                JavaScriptSerializer js = new JavaScriptSerializer();
                List<DB0010020Vm> _listDB0010020Vm = new List<DB0010020Vm>();

                string dataDB0010020vm = Request.Form["griddetailsvm"];
                if (!string.IsNullOrEmpty(dataDB0010020vm))
                {
                    _listDB0010020Vm = js.Deserialize<List<DB0010020Vm>>(dataDB0010020vm).
                    Where(d => d.IsValid == "YES").ToList();
                }
                DateTime start = DateTime.UtcNow;


                Parallel.ForEach(_listDB0010020Vm, item =>
                {
                    doDayBegin(item.BranchId);
                });

                DateTime end = DateTime.UtcNow;
                TimeSpan duration = end - start;
                return Json(new
                {
                    success = true,
                    message = "Day Begin Process Completed Successfully!" + duration
                });
            }
            catch (Exception e)
            {
                return Json(new
                {
                    success = false,
                    message = e.Message
                });

            }
        }

 public void doDayBegin(int BranchId)
        {

            using (var dbThread = new NeoSampleDBEntities()) // new db connection
            {


                EBS.DAL.Model.DB0010020 branchDetails = _idDB0010020Repository.FindOne(d => d.BranchId == BranchId);
            if (branchDetails == null)
            {
                ModelState.AddModelError("", "Branch not found!");
            }
            else
            {
                branchDetails.LastOpenDate = Convert.ToDateTime(Request.Form["LastOpenDate"]);

                OperationStatus status = _idDB0010020Repository.UpdateAndSave(branchDetails);
                if (status != null && !status.Status)
                    ModelState.AddModelError("Updation failed", status.ExceptionMessage);
            }

            EBS.DAL.Model.DB0010044 dayBegin = new DB0010044();
            dayBegin.BankId = 1;
            dayBegin.BranchId = BranchId;
            dayBegin.DayBeginFlag = 1;
            dayBegin.DayDate = Convert.ToDateTime(Request.Form["LastOpenDate"]);
            dayBegin.DayEndFlag = 0;
            dayBegin.DayEndStage = 1;
            dayBegin.DayReopenFlag = 0;
            OperationStatus status2 = _idDB0010044Repository.AddAndSave(dayBegin);
            if (status2 != null && !status2.Status)
                ModelState.AddModelError("Updation failed", status2.ExceptionMessage);
            else
            {
                CreateInwardSessionsForBranch(BranchId);
                CreateOutwardSessionsForBranch(BranchId);
            }
            }
        }


这是错误

会有什么问题?

【问题讨论】:

  • doDayBegin 方法中的内容。
  • doDayBegin 方法添加到问题@RonaldEstacion
  • 移动 var dbThread = new NeoSampleDBEntities();在类级别上,并且仅在并行操作完成后才将其处置。
  • @RonaldEstacion 我没有在任何地方使用这条线,我为了测试目的而添加了这条线。
  • 我的意思是在方法之外创建一个字段,私有 NeoSampleDBEntities dbThread = new NeoSampleDBEntities();,现在在 doDayBegin 方法中使用它而不使用 using() 块。我猜并行执行是在 FindOne 中的另一个调用完成之前处理上下文。

标签: c# asp.net-mvc linq entity-framework parallel-processing


【解决方案1】:

您在doDayBegin 方法中创建了NeoSampleDBEntities DbContext 的新实例,但是您使用了现有的(据我所知,是单个)存储库_idDB0010020Repository 的实例,大概封装了它的自己的 DbContext 实例或在构造时传入的预先存在的 DbContext 实例。

您看到的错误是由于第一个线程调用&lt;repo&gt;.FindOne 而生成模型时第二个线程调用&lt;repo&gt;.FindOne 进行DbContext 方法调用的结果。即使模型创建完成,您也很可能会遇到冲突,因为 DbContext 不是线程安全的。

根据您提出的建议,我的建议是在 doDayBegin 方法的 using 语句中创建一个新的存储库,而不是 NeoSampleDBEntities DbContext 的新实例。

【讨论】:

    【解决方案2】:

    我的猜测是调用parallel.foreach 时还没有计算_listDB0010020Vm。如果您在标准的非并行 foreach 中单步执行代码,它将通过跳过 .where 选择行进入 foreach 来显示这一点,然后当它需要列表值时,下一步将显示它跳回 where 选择器。我相信 List.ToArray 会强制它计算。尝试将该结果支付给并行循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      相关资源
      最近更新 更多