2012-04-17 8 views
6

Azureで実行されているLINQ-TO-SQLを使用するかなり大きなWebアプリケーションがあり、SQL-Azureからの一時的なエラーが発生しているため、再試行を実装する必要があります。私はそれを使用する方法の例を与えるTransient Fault Handling Frameworkし、いくつかのサイトを認識してんだけど、あなたはこれに似たもので、あなたのLINQクエリの一つ一つをラップする必要があるように見えます:LINQクエリの何百ものSQL AzureでのLINQ-TO-SQLのリトライロジック - 効率的な実装ですか?

RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5)); 
Result = retry.ExecuteAction(() => 
{ 
    … LINQ query here... 
}); 

私のデータレイヤーでは、これは本当に面倒です。さらに、結果が列挙されるまで多くの時間クエリが実際には実行されないという事実があります。たとえば、データレイヤのほとんどの関数は、リストを返すよりも柔軟性のあるビジネスレイヤまで、IQueryable <を返します。つまり、データベースの再試行ロジックでビジネスロジックレイヤーを浪費しなければならないということです。

データレイヤーでリトライロジックを維持するために、私はすべてのクエリに.ToList()を配置して、上記のレイヤーではなく、正しく実行されるようにする必要があります。

基本クラスにリトライロジックを実装し、すべてのクエリを変更する必要はないと思います。 EFのように思えますが、この問題もあります。

SQL-Azureチームに自動再試行を試して話す本当の答えは、私たちのコードでは心配する必要はありませんか?

答えて

0

LINQ to SQLではクエリをインターセプトできないため、良い解決策はわかりません。しかし、少しのコードリファクタが役に立ちます。サムシング(擬似コード)のような:

public Result QueryWithRetry(IQueryable query) 
{ 
     RetryPolicy retry = new RetryPolicy<MyRetryStrategy>(5, TimeSpan.FromSeconds(5)); 
    (() => 
    { 
     return retry.ExecuteAction(query); 
    } 
} 

今では、このメソッドを呼び出すために少し簡単です:

結果= QueryWithRetry(ここでは... LINQクエリを...)。

ただし、コードを変更してすべてのクエリを変更する必要があります。

最高のお礼、

Ming Xu。

+0

これは少し役に立ちますが、列挙されているコードの後半まで実際には実行されないクエリについてはまだ心配する必要はありませんか?したがって、私は実際に各クエリを調査し、データベースが実際に呼び出されている場所を把握しなければなりません。 – PeteShack

+0

申し訳ありませんが、私はあなたを非常によく理解できません。何かがうまくいかないと心配しているのですか?再試行の枠組みの中でクエリをラップするので、問題の原因を見つけるのがより難しくなりますか?この場合、retry.ExecuteActionにブレークポイントを設定し、コードをステップ実行することをお勧めします。 –

+0

いいえ、数百のクエリを含む既存のアプリケーションにリトライロジックを追加するのは難しい作業です。主にデータベース呼び出しがデータレイヤのlinqからSQLへのクエリで必ずしも発生しないためです。クエリの実行は、IQueryableが実際に列挙されるまで遅れることがあります。これはビジネスレイヤーで発生する可能性があります。ただ、この問題のきれいな解決策ではないようです。 – PeteShack

1

このような実装が必要な場合は、先に進んでライブラリhttps://github.com/daveaglick/LinqToSqlRetry(MITはNuGetでライセンス供与されています)を作成しました。

代わりSubmitChangesRetry()を書くことでSubmitChanges()呼び出しを再試行することができます

using(var context = new MyDbContext()) 
{ 
    context.Items.InsertOnSubmit(new Item { Name = "ABC" }); 
    context.SubmitChangesRetry(); 
} 

あなたはまた、Retry()拡張メソッドを使用してクエリを再試行することができます

using(var context = new MyDbContext()) 
{ 
    int count = context.Items.Where(x => x.Name == "ABC").Retry().Count(); 
} 

特定の再試行ロジックがポリシーによって制御可能です。ボンネットの下では、再試行メカニズムは次のようになります。

int retryCount = 0; 
while (true) 
{ 
    try 
    { 
     return func(); 
    } 
    catch (Exception ex) 
    { 
     TimeSpan? interval = retryPolicy.ShouldRetry(retryCount, ex); 
     if (!interval.HasValue) 
     { 
      throw; 
     } 
     Thread.Sleep(interval.Value); 
    } 
    retryCount++; 
} 

func()への呼び出しとretryPolicyオブジェクト内の関数は、使用状況に基づいて提供されていることを理解します。これは、リトライループ中に何が起こっているかをあなたに知らせるだけです。詳細については、リポジトリを参照してください。

関連する問題