Entity Frameworkは、デフォルトで楽観的同時実行モデルを使用します。Googleによると、楽観的とは「将来に希望と自信を持っている」という意味であり、まさにそれがEntityFrameworkの動作です。つまり、呼び出したときに、同時実行の問題が発生しないSaveChanges()
ことを「希望と自信」があるため、変更を保存しようとするだけです。
Entity Frameworkが使用できるもう1つのモデルは、悲観的な同時実行モデルと呼ばれる必要があります(「可能な限り最悪の結果を期待する」)。このモードは、エンティティごとに有効にできます。あなたの場合、Appエンティティでそれを有効にします。これが私がすることです:
手順1.エンティティの同時実行チェックを有効にする
- .edmxファイルを右クリックし、[プログラムから開く... ]を選択します。
- ポップアップダイアログで[ XML(テキスト)エディター]を選択し、[OK]をクリックします。
ConceptualModelsでAppエンティティを見つけます。アウトラインを切り替えて、必要に応じてタグを拡張することをお勧めします。あなたはこのようなものを探しています:
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
...
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="YourModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="App">
EntityTypeの下に、一連の<Property>
タグが表示されます。存在する場合Name="Status"
は、を追加して変更しConcurrencyMode="Fixed"
ます。プロパティが存在しない場合は、次の場所にコピーします。
<Property Name="Status" Type="Byte" Nullable="false" ConcurrencyMode="Fixed" />
ファイルを保存し、 .edmxファイルをダブルクリックしてデザイナビューに戻ります。
ステップ2.呼び出し時の並行性の処理SaveChanges()
SaveChanges()
2つの例外のうちの1つをスローします。おなじみのUpdateExceptionまたはOptimisticConcurrencyException。
設定されているエンティティに変更を加えた場合ConcurrencyMode="Fixed"
、EntityFrameworkは最初にデータストアに変更がないかチェックします。変更がある場合は、OptimisticConcurrencyException
がスローされます。変更がない場合は、通常どおり続行されます。
キャッチしたら、のRefresh()メソッドOptimisticConcurrencyException
を呼び出して、再試行する前に計算をやり直す必要があります。エンティティを更新するための呼び出しは、データストア内のデータを使用して競合が解決されることを意味します。同時に変更されるDownloadCountは競合です。ObjectContext
Refresh()
RefreshMode.StoreWins
これがあなたのコードをどのように見せるかです。これは、エンティティの取得と呼び出しの間に多くの操作がある場合に便利であることに注意してくださいSaveChanges()
。
private void IncreaseHitCountDB()
{
JTF.JTFContainer jtfdb = new JTF.JTFContainer();
var app =
(from a in jtfdb.Apps
where a.Name.Equals(this.Title)
select a).FirstOrDefault();
if (app == null)
{
app = new JTF.App();
app.Name = this.Title;
app.DownloadCount = 1;
jtfdb.AddToApps(app);
}
else
{
app.DownloadCount = app.DownloadCount + 1;
}
try
{
try
{
jtfdb.SaveChanges();
}
catch (OptimisticConcurrencyException)
{
jtfdb.Refresh(RefreshMode.StoreWins, app);
app.DownloadCount = app.DownloadCount + 1;
jtfdb.SaveChanges();
}
}
catch (UpdateException uex)
{
// Something else went wrong...
}
}