安らかなアーキテクチャで実装する意味がないと思われる Web サイトを作成していますが (少なくともこの問題に関連する部分ではありません)、データベースを共有する複数のサーバー間で競合状態の問題が発生しています。
私の Web サイトには別の製品のユーザーに関する情報があるため、Users テーブルがあります (ただし、私のサイトのユーザーではありません)。ユーザーには多くのファイルがあります。
ユーザーとファイルは、サイトで手動ではなく、自動化されたサービスによって設定されます。サービスはファイルをサーバーに投稿し、サーバーはファイルを解析してファイルからユーザー名を取得します。ユーザー名が新しい場合は、テーブルに新しいユーザー行が作成されます。次に、リクエストを行ったサービスにファイルについて返します。
私が見ている問題は、関連するオブジェクトに対して複数のリクエストが同時に入ったときに競合状態が発生し、データベース内の一意のインデックスの違反などを引き起こす場合です。
たとえば、ユーザー名には一意のキーがあります。このコードは、同じユーザーからのファイルに対する自動化サービスからの 2 つの要求が同時に着信した場合に問題になる可能性があります。
var myuser = db.users.FirstOrDefault(u => u.username == username);
if(myuser == null)
{
myuser = new user(username);
db.AddObject(user);
}
db.SaveChanges();
リクエスト 1 は、ユーザー名 foo を持つユーザーがいないことを確認するため、if 条件は true を返します。リクエスト 2 は、リクエスト 1 がすでにユーザーの作成を開始していることを知らずに同じことを確認し、リクエスト 2 が保存しようとすると、一意のキーに違反します。
この問題に対する一般的なパターンまたは解決策はありますか? サーバーが RESTful であれば問題ないことはわかっていますが、サービスがリクエストを行う方法を変更することは現実的ではないと思うので、可能であれば同じままにしておきたいと考えています。現時点では、そのファイルのユーザーが既に存在しているかどうか、またはそのファイルがサーバーにまだ投稿されているかどうか (複数回投稿される可能性があります) を認識せずに、ファイルをサーバーに投稿するだけです。これらのオブジェクトがまだ存在しない場合は作成され、存在する場合はアイテムのリストが更新されます。しかし、サービスに関する限り、ファイルに関する特定の情報を知りたいだけであり、データベースに既に存在するかどうかには関係ありません。
リクエストを介してユーザーを作成しようとするのは遅すぎると思います。次に、リクエストを介してファイルを作成し、別のリクエストでファイルに関する情報をリクエストします。また、このサービスは Parallel.ForEach を介して一度に複数の要求を実行するため、シングル スレッドで実行するには遅すぎます。