0

私は現在、このようなオブジェクトを持っています(簡略化):

public class Image {
    public int Id { get; set; }

    public int ExternalId { get; set; }
}

今、私がこのメソッドを持っているとしましょう (ほとんどが疑似コード):

public void GetImage(int externalId) {
    var existingImage = db.Images.FirstOrDefault(i => i.ExternalId == externalId);

    if (existingImage != null) {
        return existingImage;
    }

    var newImage = new Image() { ExternalId = externalId };
    db.Images.Attach(newImage);
    db.SaveChanges();

    return newImage;
}

ExternalId はキーではないため、変更トラッカーは、トラッカーに「重複した」画像があっても気にしません。

では、このメソッドが AJAX と Web API を介して同時に 2 回呼び出されるとします (現在のシナリオ)。これは非同期なので、現在このメソッドを呼び出すスレッドが 2 つあります。

呼び出し間の時間が十分に短い場合 (私の場合はそうです)、既存のチェックでは行が返されないため、同じ外部 ID を持つ 2 つの行がデータベースに追加されます。実際の例では、サービスから「イメージ」を取得するときにタイミングの問題があるため、この例を大幅に簡略化しました。

どうすればこれを防ぐことができますか? 新しいか更新されたかに関係なく、画像を返す必要があります。データベースに一意の制約を追加したため、例外が発生しましたが、クライアントでは、例外をスローする代わりに既存のイメージを使用する必要があるのに、呼び出しが失敗します。

EF を正しく理解していればExternalId、主キーを作成し、同時実行を使用してこれを処理することでこれを処理できますよね? 現在のモデルを変更しないようにする方法はありますか、それともこれが唯一の選択肢ですか?

4

1 に答える 1

1

エンティティの一意性を定義するプロパティ ( ExternalId) が既にある場合は、エンティティの実際の一意性を指定しない別のダミー キーを作成する代わりに、それをキーとして使用する必要があります。キーとして使用しない場合ExternalIdは、データベースのその列に一意の制約を設定し、データベースImageから既存のものをロードするためにコードで例外を処理する必要があります。

于 2012-12-23T23:02:40.497 に答える