2017-04-08 61 views
2

我這就要求我的WebAPI同時有兩個控制檯應用程序和我回去在控制檯應用程序從我的API後續反應:C#的WebAPI異步方面的問題

第二次手術就這樣開始了上下文之前一先前的異步操作完成。在調用此上下文中的另一個方法之前,請使用'await'來確保任何異步操作已完成。任何實例成員不保證是線程安全的。

所以他們在同一時間調用我的webapi,然後webapi內的某些東西無法處理這兩個異步調用,因此返回此錯誤。

我檢查了webapi項目上的所有代碼,所有的方法都是異步的,所以我不明白爲什麼我會得到這個。

這是webapi的代碼。

控制器:

public class FederationsController : ApiController 
{ 
    private readonly IFederationRepository _federationRepository; 

    public FederationsController(IFederationRepository federationRepository) 
    { 
     _federationRepository = federationRepository; 
    } 

    [HttpGet] 
    [Route("federations", Name = "GetFederations")] 
    public async Task<IHttpActionResult> GetFederations() 
    { 
     var federations = await _federationRepository.GetAllAsync(); 
     return Ok(federations.ToModel()); 
    } 
} 

public class FederationRepository : IFederationRepository, IDisposable 
{ 
    private Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext(); 

    #region IQueryable 
    private IQueryable<Models.Entities.Federation> FederationWithEntities() 
    { 
     return _db.Federations.Include(x => x.Clubs) 
           .Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue)); 
    } 
    #endregion IQueryable 

public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync() 
    { 
     return await FederationWithEntities().ToListAsync(); 
    } 
} 

映射器

public static class FederationMapper 
{ 
    public static List<Federation> ToModel(this IEnumerable<Models.Entities.Federation> federations) 
    { 
     if (federations == null) return new List<Federation>(); 
     return federations.Select(federation => federation.ToModel()).ToList(); 
    } 

    public static Federation ToModel(this Models.Entities.Federation federation) 
    { 
     return new Federation() 
     { 
      Name = federation.Name, 
      FederationCode = federation.FederationCode, 
      CreatedAt = federation.CreatedAt, 
      UpdatedAt = federation.UpdatedAt 
     }; 
    } 
} 

的DbContext

public class CompetitionContext : DbContext 
{ 
    public CompetitionContext() : base("ContextName") 
    { 
    } 

    public DbSet<Federation> Federations { get; set; } 
} 

UnityConfig

public static class UnityConfig 
{ 
    public static void RegisterComponents() 
    { 
     var container = new UnityContainer(); 
     container.RegisterType<IFederationRepository, FederationRepository>(); 
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container); 
} 
} 

感謝您所有的意見/幫助。

+3

我會檢查看看是否有導致您的統一登記搞砸,它表現得像一個IFederationRepository是在請求之間共享。嘗試在統一註冊中明確地設置一個'TransientLifetimeManger'來查看它是否改變了任何東西。 –

+0

@ScottChamberlain我試過這個container.RegisterType (new HierarchicalLifetimeManager());但如果那是你的意思,那也沒有解決問題。 – Nick

+1

'HierarchicalLifetimeManager'是使用絕對錯誤的管理器,您需要每個解決方案的類的新副本。你需要一個'TransientLifetimeManger' –

回答

0

在你的倉庫中,你正在創建一個單一的CompetitionContext並重用它。我假設IoC安裝程序將存儲庫註冊爲某種單一實例,因此每次都使用同一個存儲庫。如果是這種情況,您應該爲每個方法調用創建一個新的CompetitionContext。

此外,可能應該確保它使用using語句關閉。

我也不清楚你的代碼片段爲什麼你從這個FederationWithEntities方法返回一個IQueryable,你還有其他的東西在使用它嗎?

不管怎樣,我可能會改變GetAllMethod是這樣的:

public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync() 
{ 
    using (Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext()) 
    { 
    return _db.Federations.Include(x => x.Clubs) 
          .Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue)) 
          .ToListAsync(); 
    } 
} 
+0

或確保上下文是每個請求。 –

+0

RegisterType每次調用控制器的構造函數時都應該默認創建一個新的FederationRepository,並且每個請求調用構造函數一次。每個新的'FederationRepository'都會創建一個新的'CompetitionContext'。 –

+0

我試過這個解決方案,但並沒有解決問題。 – Nick