トランザクションの明示的なスコープ制御をEF6の Code First で行う方法をご紹介します。
※Entity Framework Core でのトランザクション制御については Microsoft Docsで詳しく解説されています。
※Model/Database First の場合は「トランザクションのスコープ制御(EF4.1~)」「トランザクションのスコープ制御(EF6)」をご覧ください。
複数回の SaveChanges をまたぐトランザクション
// コンテキストusing(varcontext=newNorthwindContext()){// トランザクション開始using(vartransaction=context.Database.BeginTransaction()){// 1つめの SaveChanges()varproduct=awaitcontext.Products.SingleAsync(p=>p.ProductID==1).ConfigureAwait(false);product.ProductName="New Product Name";awaitcontext.SaveChangesAsync().ConfigureAwait(false);// 2つめの SaveChanges()varemployee=awaitcontext.Employees.SingleAsync(e=>e.EmployeeID==1).ConfigureAwait(false);employee.Title="New Title";awaitcontext.SaveChangesAsync().ConfigureAwait(false);// まとめてコミットtransaction.Commit();}}
複数のコンテキストをまたぐトランザクション
// 接続準備// Model/Database First と異なり、EntityConnection を介しません。using(varsqlConnection=newSqlConnection(NorthwindContext.GetConnectionString())){// あらかじめ接続を開いておく。sqlConnection.Open();// トランザクション開始using(vartransaction=sqlConnection.BeginTransaction()){// 1つ目のコンテキストを操作する。using(varcontext=newNorthwindContext(sqlConnection,false)){context.Database.UseTransaction(transaction);varproduct=awaitcontext.Products.SingleAsync(p=>p.ProductID==1).ConfigureAwait(false);product.ProductName="New Product Name";awaitcontext.SaveChangesAsync().ConfigureAwait(false);}using(varcontext=newNorthwindContext(sqlConnection,false)){context.Database.UseTransaction(transaction);varemployee=awaitcontext.Employees.SingleAsync(e=>e.EmployeeID==1).ConfigureAwait(false);employee.Title="New Title";awaitcontext.SaveChangesAsync().ConfigureAwait(false);}// まとめてコミットtransaction.Commit();}}// コンテキストクラスpublicclassNorthwindContext:DbContext{:/// <summary>/// コンストラクタ。/// </summary>/// <param name="existingConnection">コンテキストで使用する接続。</param>/// <param name="contextOwnsConnection">false を指定すると、コンテキストが Dispose されたときに接続を Dispose しない。</param>publicNorthwindContext(DbConnectionexistingConnection,boolcontextOwnsConnection):base(existingConnection,contextOwnsConnection){}/// <summary>/// 接続文字列を取得する。/// </summary>/// <returns></returns>publicstaticstringGetConnectionString(){using(varcontext=newNorthwindContext()){returncontext.Database.Connection.ConnectionString;}}:}