0

助けが必要な非常に重要な質問があります。問題を次の例に落とし込もうとします。

次のように wcf/web サービスを実装します (ただし、他のモジュールにすることもできます)。

public class Svc: ISvc
{
   public void PerformSimpleOperations()
   {
      try
      {
          // insert in other tables here (calling stored procs)

          /* important line here */
          dbHandler.InsertRecordInSpecificTable(recordType1);

          // commit transaction (default isolation level)
          dbHandler.CommitTransactDB();
      }
      catch
      {
          dbHandler.RollbackTransactDB();
      }
   }
   public void PerformComplexOperations()
   {
      try
      {
          // some complex operations here involving db (calling stored procs)

          /* important lines here */
          dbHandler.InsertRecordInSpecificTable(recordBEGIN);    
          foreach (var recordType2 in arrayOfRecordsType2)
              dbHandler.InsertRecordInSpecificTable(recordType2);    
          dbHandler.InsertRecordInSpecificTable(recordEND);    

          // commit transaction (default isolation level)
          dbHandler.CommitTransactDB();
      }
      catch
      {
          dbHandler.RollbackTransactDB();
      }
   }
}

データベース内の 1 つの 'SpecificTable' にトランザクション ベース(デフォルトの分離レベルのADO.NET SQLTransaction) でレコードを挿入する 2 つの異なるメソッドがあります (もちろん、異なるスレッドによっていつでも呼び出されます)。

例でわかるように、最初のメソッドは'type1' の単純なレコードを挿入するだけですが、2 番目のメソッドはいくつかの 'BEGIN'および'END'識別子で始まる'type2' の大量のレコードを挿入するため、この束は後で別のアプリケーションによって全体として処理されます。

すべてのレコードには自動インクリメンタル ID があるため、私の意図は、このテーブルの'BEGIN' と 'END' の間に'type2' のレコードのみを含めることです。

質問: このテーブルで、' BEGIN'レコードと'END'レコードの間に、 'type1' のスリップ レコードがある可能性はありますか?

私の知る限り、そのトランザクション中はデータベースをロックする必要があり(デフォルトの分離レベル)、通常はこの動作は発生しないため、私の実装は正しいはずです。それは正しいですか、それともここで重要なことを見逃していますか?

どうもありがとう!

4

2 に答える 2

2

デフォルトのトランザクション分離レベルはREAD COMMITTED- つまり、変更されていないコミットされていないデータを読み取ることはできません。これはテーブル ロックではなく、一度に 1 つの操作しか実行できないことも保証しません。

おそらくSERIALIZABLE、コードのより良いオプションです。

http://msdn.microsoft.com/en-us/library/ms173763.aspx

于 2012-09-19T10:42:17.900 に答える
2

あなたはすべての重要な詳細を省略しています...

  • どのようなトランザクションを使用しますか?
    • TransactionScopeオブジェクト?
    • SqlTransactionオブジェクト?
    • 露骨なBEGIN TRANSACTION発言?
    • WFC サービスがトランザクションを要求するものとしてマスクされているか、またはバインディングがトランザクションをフローしているか?

これらすべてが答えに大きく影響します。

しかし、もっと重要なことは、あなたの発言にはいくつかの非常に危険な誤謬があります。

私の意図は、このテーブルの「BEGIN」と「END」の間に「type2」のレコードのみを含めることです。

このステートメントは意味がありません。それは単に存在しない概念を使用しています:「テーブル内のレコード...の間」。テーブル内のレコードは、他のレコードの前でも後でもなく、他のレコードの間にもありません。順序の概念をテーブルに適用することはできません。概念として、順序は結果にのみ存在します。SELECT の戻り値であり、明示的なORDER BY句が追加されている場合を除いて未定です。したがって、1 つのアトミック リターンで挿入されたすべてのレコードを取得したいのでPerformComplexOperation、質問を言い換えることができます。その答えは、適切なキーを使用することです。

  • 呼び出しのキー値を生成する
  • 挿入された各レコードは、このキーを列の値として使用します
  • 検索は、WHEREこのキーのみをフィルタリングするための適切な句を追加します

全体的に、理解を超えて問題を単純化しました。よくわからない概念を使用して抽象的な質問を投稿するのではなく、実際のデータ モデル スキーマと実際のコードを、発生した問題と共に投稿してください。

于 2012-09-19T10:47:36.037 に答える