【问题标题】:C# ef second operation started before previous asynchronous operation completedC# ef 第二个操作在前一个异步操作完成之前开始
【发布时间】:2018-05-22 06:42:22
【问题描述】:

只是尝试对 ef 进行正常查询,但收到以下错误消息

“在前一个异步操作完成之前,在此上下文上启动了第二个操作”

我正在对所有 aync 调用使用 await,但不确定是什么导致了这个问题。

这里的代码

    var sids = await context.Sites.Where(s => slist.Contains(s.JVSiteID)).ToListAsync();

    var header = await context.GenericCsvHeaders.FirstOrDefaultAsync(x => x.Header == csvh) ?? new GenericCsvHeader { Header = csvh };

    context.Entry<GenericCsvHeader>(header).State = (header.GenericCsvHeaderID == 0) ? EntityState.Added : EntityState.Unchanged;

    var sa = await context.SAs.Where(x => x.StatusID == Data.Enum.Status.Active && mapkeys.Contains(x.SAName)).Select(x => new { x.SAName, x.SACode, x.SAID }).ToListAsync();

    if (sa.Count > 0)
        sasitelist = await context.Site_SA.Where(x => x.StatusID == Data.Enum.Status.Active && siteids.Contains(x.SiteID ?? 0)).ToListAsync();

    var az = await context.Azimuths.Where(x => x.StatusID == Data.Enum.Status.Active && mapkeys.Contains(x.AzimuthName)).Select(x => new { x.AzimuthName, x.AzimuthID }).ToListAsync();

    if (az.Count > 0)
           azsitelist = await context.Site_Azimuth.Where(x => x.StatusID == Data.Enum.Status.Active && siteids.Contains(x.SiteID ?? 0)).ToListAsync();

    var rows = new List<dynamic>(); //getting this list from csv file via csvHelper

     foreach (var r in rows)
       {
           var s = sids.FirstOrDefault(x => x.JVSiteID == (((IDictionary<String, Object>)r)[siteid]).ToString()) ?? new Site();
            UpdateSite(s, r, map);
       }


    private async void UpdateSite(Site site, dynamic csvSite, IDictionary<string, string> map)
    {

       context.Entry(site).State = (site.StateID == 0) ? EntityState.Added : EntityState.Modified;
       site.SiteForAuditTrail = site;
       if (map.ContainsKey("SiteName") && !String.IsNullOrWhiteSpace(GetStringOfDynamic(map,csvSite,"SiteName")))
             site.SiteName = GetStringOfDynamic(map,csvSite, "SiteName");

       if (map.ContainsKey("State") && !String.IsNullOrWhiteSpace(GetStringOfDynamic(map,csvSite, "State")))
         {
            //getting exception at below line
             var state = (await GetRefTypeList<State>(x => x.StateCode == GetStringOfDynamic(map,csvSite, "State"))) ?? new State { StateCode = GetStringOfDynamic(map,csvSite, "State") };

          context.Entry(state).State = (state.StateID == 0) ? EntityState.Added : EntityState.Unchanged;
           site.State = state;
          state.SiteForAuditTrail = site;
     }

  }


private async Task<T> GetRefTypeList<T>(Func<T, bool> expression) where T : EntityBase
 {
       if (!refTypes.ContainsKey(typeof(T).Name))
              refTypes[typeof(T).Name] = (await context.Set<T>().Where(x => x.StatusID == Data.Enum.Status.Active).ToListAsync());

       return (refTypes[typeof(T).Name] as List<T>)?.FirstOrDefault(expression);
 }


private string GetStringOfDynamic(IDictionary<string, string> map,dynamic obj, string propertyName)
 {
    if (((IDictionary<String, Object>)obj).ContainsKey(map[propertyName]))
          return (((IDictionary<String, Object>)obj)[map[propertyName]]??"").ToString();

         return "";
 }

【问题讨论】:

    标签: c# .net entity-framework asynchronous async-await


    【解决方案1】:

    发现问题,调用 UpdateSite 时缺少 await

     foreach (var r in rows)
           {
               var s = sids.FirstOrDefault(x => x.JVSiteID == (((IDictionary<String, Object>)r)[siteid]).ToString()) ?? new Site();
              **await**  UpdateSite(s, r, map);
           }
    

    【讨论】:

      【解决方案2】:

      您在这里遇到了竞争条件。当您使用 await 时,您可能会在返回变量 sids、header、sa 和 az 之前执行其他代码。

      您应该重构您的代码,以便在返回这些变量之前不会执行剩余的代码。您可以通过使用任务然后使用扩展名WhenAll 来执行此操作,这将确保在继续之前完成每个等待。 Here is a link to MS docs on Task and WhenAll implementation

      【讨论】:

      • “当您使用 await 时,您可能会在变量 sids、header、sa 和 az 被返回之前执行其他代码”对此不太清楚。 sids 是该方法开始之前的地方,我正在使用 csvHelper 读取 csv 文件并使用 ef。你能解释一下上面的陈述吗?谢谢
      • 认为 Task 和 WhenAll 的用途是不同的,当你想做类似 list> tasks 的事情时;任务.add(GetAsync(1));任务.add(getAsync(2));等待 Task.whenAll(tasks);
      猜你喜欢
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2014-12-08
      相关资源
      最近更新 更多