C#ef第二个操作在前一个异步操作完成之前启动

时间:2017-12-08 03:24:40

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

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

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

我正在使用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 "";
 }

2 个答案:

答案 0 :(得分:1)

你在这里遇到了竞争条件。当您使用等待时,您可能会在变量sid,header,sa和az之前执行其他代码。

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

答案 1 :(得分:1)

发现问题,在调用UpdateSite时错过了等待

 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);
       }