0

MVC Web アプリケーションを開発しています。

つまり、ビュー、モデル、ビュー モデルを作成しています。データベース プロバイダーとして linq-to-sql を使用し、カスタムUnit-of-Workパターンを実装しました。また、(私の実装では) 完全に見え、直接SQLコードから完全に分離されたデータ ソース、リポジトリ、およびサービス パターンも実装しました。実際、単体テスト用に設計された任意のデータベースから、データベースに影響を与えずにインメモリ データ ソースを使用してアプリケーションをテストできました。

最終的に、1 つの問題に行き詰まります。クロス スレッド (またはクロス プロセス。私の知る限り、IISは 1 つの Web アプリで複数のアプリ ドメインを作成できるため) 操作に対する保護がありません。

たとえば、いくつかのレコードを含むテーブルがあります。そして、時々 Web リクエストが発生します (コントローラー内、サービス内、リポジトリ内) 列の最大数で SQL テーブルの行を選択しTicketId、そのテーブルに別の行を挿入します(that column value + 1)

2 つ以上のスレッドまたはプロセスが同じことを行う場合、重複した値がデータベースに表示される可能性があります。しばらく前に、私の webapp が少し小さかったとき、私は直接 SQL コードを使用し、単純なUPDLOCKSELECTステートメントでブロックを使用して、変更中のレコード (またはその他のもの) をロックし、他のすべてのデータベース クライアントが終了するまで待機するのを防ぎました。TransactionScope

これらすべてのパターンで、私は 1 つのことを忘れていました:
データベースのマルチアクセス保護の問題を実際に実装するにはどうすればよいですか?
直接の SQL コードなし。

4

2 に答える 2

4

データベースのマルチアクセス保護の問題を実際に実装するにはどうすればよいですか?

それを行うのはデータベース エンジンの仕事です。問題が報告された場合にアプリが適切に失敗するようにするのは、あなたの仕事です。データベース エンジンでのロック を参照してください。

たとえば、いくつかのレコードを含むテーブルがあります。そして、時々 Web リクエストが発生します。これは、(コントローラー内、次にサービス、次にリポジトリ内で) 最大の SQL テーブルの行を選択し、たとえば TicketId 列としましょう。そのテーブルに別の行を (その列の値 + 1 )。

ここで、データベースの動作を再現しようとしていることを考えると、データベースをあまり信頼していないように見えるという印象を受けました。フィールドを に設定するauto-incrementと、問題が解決するはずです。独自の手動自動インクリメントを実装する必要がある場合は、本質的に競合状態であるため、何らかの形式のロックを使用する必要があります。

private static object lockObject = new Object();

lock(lockObject)
{
    ... DB stuff
}

クロスプロセス ロックの場合は、おそらく名前付きMutexを確認する必要があります。

于 2012-10-15T14:09:49.880 に答える
1

なぜ単一のテーブルを使用してチケット番号を表し、Seriliazable トランザクション分離レベルでトランザクションを使用しないのですか?

int GetTicketNumber(bool shouldIncrement)
{

   if(shouldIncrement)
   {
     // use transaction with serilizable isolation level
     select and update
   }
   else
   {
     //just select
   }

}
于 2012-10-16T10:16:12.853 に答える