Help us understand the problem. What is going on with this article?

[Entity Framework] トランザクションのスコープ制御(EF6:Code First)

Entity Framework のコンテキストにおいて、トランザクションは、既定では SaveChanges() を実行したときに暗黙的に使用されます。

要件によっては、トランザクションのスコープを明示的に制御したいケースも出てくるでしょう。
ここではトランザクションの明示的なスコープ制御を EF6 の Code First で行う方法をご紹介します。

※Entity Framework Core でのトランザクション制御については Microsoft Docs で詳しく解説されています。
※Model/Database First の場合は「トランザクションのスコープ制御(EF4.1~)」「トランザクションのスコープ制御(EF6)」をご覧ください。

複数回の SaveChanges をまたぐトランザクション

Database.BeginTransaction でトランザクションを開始し、その中で SaveChanges した変更をまとめて Commit します。

// コンテキスト
using (var context = new NorthwindContext())
{
    // トランザクション開始
    using (var transaction = context.Database.BeginTransaction())
    {
        // 1つ目の SaveChanges()
        var product = await context.Products.SingleAsync(p => p.ProductID == 1).ConfigureAwait(false);
        product.ProductName = "New Product Name";
        await context.SaveChangesAsync().ConfigureAwait(false);

        // 2つ目の SaveChanges()
        var employee = await context.Employees.SingleAsync(e => e.EmployeeID == 1).ConfigureAwait(false);
        employee.Title = "New Title";
        await context.SaveChangesAsync().ConfigureAwait(false);

        // まとめてコミット
        transaction.Commit();
    }
}

複数のコンテキストをまたぐトランザクション

あらかじめ接続を開いておいて BeginTransaction メソッドでトランザクションを開始し、その中で複数のコンテキストを操作、SaveChanges した後にまとめて Commit します。

Model/Database First と異なり、コンテキストのコンストラクタに渡す接続は EntityConnection を介しません。
コンテキストを Dispose しても接続が破棄されないよう、contextOwnsConnection 引数には false を指定します。

トランザクションは Database.UseTransaction メソッドでコンテキストに渡して共用します。

// 接続準備
using (var sqlConnection = new SqlConnection(NorthwindContext.GetConnectionString()))
{
    // あらかじめ接続を開いておく。
    sqlConnection.Open();

    // トランザクション開始
    using (var transaction = sqlConnection.BeginTransaction())
    {
        // 1つ目のコンテキストで保存
        using (var context = new NorthwindContext(sqlConnection, false))
        {
            context.Database.UseTransaction(transaction);

            var product = await context.Products.SingleAsync(p => p.ProductID == 1).ConfigureAwait(false);
            product.ProductName = "New Product Name";
            await context.SaveChangesAsync().ConfigureAwait(false);
        }

        // 2つ目のコンテキストで保存
        using (var context = new NorthwindContext(sqlConnection, false))
        {
            context.Database.UseTransaction(transaction);

            var employee = await context.Employees.SingleAsync(e => e.EmployeeID == 1).ConfigureAwait(false);
            employee.Title = "New Title";
            await context.SaveChangesAsync().ConfigureAwait(false);
        }

        // まとめてコミット
        transaction.Commit();
    }
}

// コンテキストクラス
public class NorthwindContext : DbContext
{
    :

    /// <summary>
    /// コンストラクタ。
    /// </summary>
    /// <param name="existingConnection">コンテキストで使用する接続。</param>
    /// <param name="contextOwnsConnection">false を指定すると、コンテキストが Dispose されたときに接続を Dispose しない。</param>
    public NorthwindContext(DbConnection existingConnection, bool contextOwnsConnection)
        : base(existingConnection, contextOwnsConnection)
    {
    }

    /// <summary>
    /// 接続文字列を取得する。
    /// </summary>
    /// <returns></returns>
    public static string GetConnectionString()
    {
        using (var context = new NorthwindContext())
        {
            return context.Database.Connection.ConnectionString;
        }
    }

    :
}
CodeOne
【品質と生産性にこだわるシステム開発】 .NET(C#/VB.NET)専門・リモート開発歴10年。即日・1時間から頼める常駐しないエンジニア。確かな技術で開発チームを手堅くサポートします。
https://codeone.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした