2017-04-08 14 views
2

私は私のWEBAPI同じ時間を呼び出す2つのコンソールアプリケーションを持って、私は戻って私のAPIからのフォロー応答はコンソールアプリケーションで取得:C#のWEBAPI非同期コンテキスト問題

は、第2の操作をする前に、この文脈で開始しました以前の非同期操作が完了しました。このコンテキストで別のメソッドを呼び出す前に、非同期操作が完了したことを確認するには、 'await'を使用します。どのインスタンスメンバーもスレッドセーフであるとは限りません。

したがって、私のwebapiを同時に呼び出すと、webapi内の何かがこれらの2つの非同期呼び出しを処理できないため、このエラーが返されます。

私は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 (新しいHierarchicalLifetimeManager())を試しました。それはあなたが意味するものであれば問題を解決しませんでしたか? – Nick

+1

'HierarchicalLifetimeManager'は絶対に間違ったマネージャーです。あなたは解決ごとにクラスの新しいコピーが必要です。'TransientLifetimeManger'が必要です –

答えて

0

あなたのリポジトリでは、1つの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'を作成する必要があり、コンストラクタはリクエストごとに1回呼び出されます。新しい 'FederationRepository'は新しい' CompetitionContext'を作成します。 –

+0

私はこの解決策を試みましたが、問題を解決しません。 – Nick