2012-01-09 18 views
1

私は理解できない動作があります。私はRavenDBを使用しており、各作業単位にセッションを使用しています。ロジッククラスがRavenDBデータアクセス層(DAL)を呼び出すと、新しいセッションが作成されます。 DAL内では、他のDALクラスおよびメソッドを呼び出すことができますが、1つのセッションだけが使用されます。RavenDB IEnumerable vs List

私が理解できない部分は、以下のGetMostRecentByStartTime()メソッド内でIEnumerableとListを使用することの違いです。その方法では、ちょうど示されているもののようなリストを使用して、これは私の出力である:リストを使用して

:ちょうどセッションを閉じる前にリクエストの
数:2
だけでセッションを閉じる前にリクエストの数:4
要求の数セッションを閉じる直前:6
セッションを閉じる直前のリクエスト数:7

注:これらの時間はセッションが実際に閉じられるわけではありません。最後の時間の後にのみ。元々呼ばれていたDALメソッドが完了したときにのみセッションを終了します。

私は(そしてそれは私が作るのみ変更です)IEnumerableを持つリストのすべてのインスタンスを置き換えるならば今、私はこの出力を得る:IEnumerableをを使用して

:リクエストの
数だけセッションを閉じる前に:2ちょうどセッションを閉じる前にリクエストの
数:3
だけでセッションを閉じる前にリクエストの数:要求の4
数だけセッションを閉じる前に:27

なぜ違いがありますか?

別の問題は、アプリケーション内に新しいInstallationSummaryオブジェクトを追加すると、IEnumerableアプローチを使用してリクエスト数が増加するという別の問題です。なぜか分からない。 Listアプローチを使用すると、さらに多くのInstallationSummaryオブジェクトを追加した後でも、要求カウントは同じままです。誰もそれを説明することはできますか?上記の方法が呼び出されますのはここ

public IEnumerable<InstallationSummary> GetMostRecentByStartTime(int numberToRetrieve) 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 

    try 
    { 
     return ExecuteQuery<IEnumerable<InstallationSummary>>(() => 
     { 
      List<InstallationSummary> installationSummaries = 
       QueryAndCacheEtags(session => session.Advanced.LuceneQuery<InstallationSummary>() 
       .Include(x => x.ApplicationServerId) 
       .Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId) 
       .Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId) 
       .OrderByDescending(summary => summary.InstallationStart) 
       .Take(numberToRetrieve)).Cast<InstallationSummary>().ToList(); 

      List<string> appServerIds = (from item in installationSummaries select item.ApplicationServerId).ToList(); 
      List<string> appIds = (from item in installationSummaries select item.ApplicationWithOverrideVariableGroup.ApplicationId).ToList(); 
      List<string> groupIds = (from item in installationSummaries select item.ApplicationWithOverrideVariableGroup.CustomVariableGroupId).ToList(); 

      List<ApplicationServer> appServers = new ApplicationServerData().GetByIds(appServerIds).ToList(); 
      List<Application> apps = new ApplicationData().GetByIds(appIds).ToList(); 
      List<CustomVariableGroup> groups = new CustomVariableGroupData().GetByIds(groupIds).ToList(); 

      foreach (InstallationSummary summary in installationSummaries) 
      { 
       summary.ApplicationServer = appServers.Where(server => server.Id == summary.ApplicationServerId).FirstOrDefault(); 

       summary.ApplicationWithOverrideVariableGroup.Application = 
        apps.Where(app => app.Id == summary.ApplicationWithOverrideVariableGroup.ApplicationId).FirstOrDefault(); 

       if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId == null) { continue; } 

       summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup = 
        groups.Where(group => group.Id == summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId).FirstOrDefault(); 
      } 

      return installationSummaries; 
     }); 
    } 
    finally 
    { 
     stopwatch.Stop(); 
     Debug.WriteLine("InstallationSummaryData.GetMostRecentByStartTime(): " + stopwatch.ElapsedMilliseconds); 
    } 
} 

は次のとおりです。

protected T ExecuteQuery<T>(Func<T> func) 
{ 
    if (func == null) { throw new ArgumentNullException("func"); } 

    try 
    { 
     return func.Invoke(); 
    } 
    finally 
    { 
     Debug.WriteLine("Number of requests just before closing session: " + _session.Advanced.NumberOfRequests); 
     CloseSession(); 
    } 
} 

答えて

5

まず、あなたはすべてのあなたのIListsを交換し、IEnumerablesと交換した場合、それはマイナーな変更ではありません。主な違いは、がIEnumerablesで遅延実行され、IListを使用しているときはいつも熱心に実行していることです。この違いを認識していない場合は、多くの問題が発生する可能性があります。

あなたのケースでは、RavenDBの.Include<T>()機能の遅延実行と間違った使用の組み合わせが原因です。後者は、クライアントDocumentSession内のインクルードされたドキュメントをキャッシュすることにより、データベースへのリモート呼び出しの回数を減らすことを目的としています。 DocumentSession.Load<T>()を使用すると効果的ですが、DocumentSession.Query<T>().Where(x => x.Id == id)を使用してドキュメントを取得しても差はありません。あなたがNHibernateに慣れているなら、これはあなたの最初のレベルのキャッシュです。それはあなたのコードを変更し、代わりにこれを使用して、作業を取得するために

List<InstallationSummary> installationSummaries = 
    QueryAndCacheEtags(session => session.Advanced.LuceneQuery<InstallationSummary>() 
    .Include(x => x.ApplicationServerId) 
    .Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId) 
    .Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId) 
    .OrderByDescending(summary => summary.InstallationStart) 
    .Take(numberToRetrieve)).Cast<InstallationSummary>().ToList(); 

foreach (InstallationSummary summary in installationSummaries) 
{ 
    summary.ApplicationServer = session.Load<ApplicationServer>(summary.ApplicationServerId); 

    summary.ApplicationWithOverrideVariableGroup.Application = 
     session.Load<Application>(summary.ApplicationWithOverrideVariableGroup.ApplicationId); 

    if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId != null) 
     summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup = 
      session.Load<CustomVariableGroup>(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId); 
} 
+0

えーえ...それはもっと清潔です。私は今日までこれを試すことができません。私はそれがどのように進むのかを知らせます。ありがとう! –

+0

うわー、どういう違いがありますか?要求数は1に減少し、400ではなく40ミリ秒かかりました。もう一度ありがとう、ダニエル。 –

関連する問題