Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9743

Entity Framework Coreで行ロックを取得する方法

$
0
0

Entity Framework Coreで行ロックを取得する方法

Entity Framework Core(以下EF Core)でデータ取得と同時に更新ロック(行ロック)をかける方法を紹介します。
SQLで記述した場合、以下のようなクエリに対応する処理です。

-- SQL ServerSELECT*FROM[TABLE_NAME]WITH(UPDLOCK)-- OracleSELECT*FROM[TABLE_NAME]FORUPDATE

以下の環境で動作確認を行っています。

  • .NET Core 3.1 (C# 8.0)
  • Microsoft SQL Server 2016 Express Edition
  • Entity Framework Core 5.0.4

更新ロックを取得する方法

調べた限りではEF Coreは標準で更新ロックを取得する仕組みを提供していないようです。
その為、生SQLクエリを使用する方法で対応します。

// dbSet は DbContext と紐づけられた DbSet<T> のインスタンスですdbSet.FromSqlRaw<T>($"SELECT * FROM [{テーブル名}] WITH (UPDLOCK)")

FromSqlRawメソッドはIQueryable<T>を返すため、続けてWhereメソッド等で対象を絞り込むクエリが実現できます。

繰り返し使用することになると思いますので、共通メソッドを定義すると良いと思われます(以下の例は拡張メソッドとして記述しています)。
その際、クエリを作成するためにテーブル名が必要となりますので、何らかの方法で取得する必要があります。
テーブル名がエンティティ型のクラス名と一致する場合は以下のように書けます(Tはエンティティ型とします)。

publicstaticIQueryable<T>ForUpdate<T>(thisDbSet<T>dbSet)whereT:class{returndbSet.FromSqlRaw<T>($"SELECT * FROM [{typeof(T).Name}] WITH (UPDLOCK)");}

クラス名がテーブル名と異なる場合は、エンティティクラスにTable属性1でテーブル名を対応づけ、これを参照するのが簡単です。2

publicstaticIQueryable<T>ForUpdate<T>(thisDbSet<T>dbSet)whereT:class{vartable=(TableAttribute)Attribute.GetCustomAttribute(typeof(T),typeof(TableAttribute));returndbSet.FromSqlRaw<T>($"SELECT * FROM [{table.Name}] WITH (UPDLOCK)");}

更新ロックの必要性について

通常、EF CoreはUPDATE等の更新クエリはSaveChangesメソッドを実行した時点で発行される為、ロックを取得する時間が最小限となります。

// context は DbContext のインスタンスですusingvartransaction=context.Database.BeginTransaction();try{varentities=context.Table.ToList();  // この時点ではロックは取得しない// データ編集等if(context.SaveChanges()>0){// SaveChangesメソッドで更新系クエリが発行され、更新ロックが取得され、// Commitを行うまでの間ロックが保持されるtransaction.Commit();}}catch{transaction.Rollback();}

ロックの競合を防ぐ観点ではこのままでも良いのですが、データ編集のコストが高い場合にデータの取得から実際に更新を行うまでの間隔が長くなってしまい、他者の更新等が割り込まれてデータの不整合を引き起こす可能性が高まります。
そういった場合ではデータを取得した時点で更新ロックを取得し、データ編集処理中のDB変更を抑制する必要があります。


  1. Table属性: System.ComponentModel.DataAnnotations.Schema.TableAttribute 

  2. エンティティクラスにTable属性を付与する方法は以下を参照ください。
    https://docs.microsoft.com/ja-jp/ef/core/modeling/entity-types?tabs=data-annotations 


Viewing all articles
Browse latest Browse all 9743

Trending Articles