上下文之间的事务

2023-11-27

我正在使用 Entity Framework Core (7) 开发一个控制台应用程序。

该应用程序分为 3 个不同的区域,但数据库是共享的。 我创建了3个不同的DbContext现在我需要在它们之间执行交易。 所以我需要一个原子操作来保存所有更改或不保存任何内容(回滚)。

我知道在 Entity Framework 6 中有一个类叫做TransactionScope但我在 EF Core 中找不到替代方案。

使用以下代码:

public static void Main(string[] args)
    {
        var options = new DbContextOptionsBuilder<DbContext>()
        .UseSqlServer(new SqlConnection("Server=x.x.x.x,1433;Database=test;user id=test;password=test;"))
        .Options;

        var cat = new Cat { Name = "C", Surname = "C", Age = 55 };
        var dog = new Dog { Date = DateTime.Now, Code = 120, FriendId = cat.Id };

        using (var context1 = new DogsContext(options))
        {
            using (var transaction = context1.Database.BeginTransaction())
            {
                try
                {
                    context1.Dogs.Add(dog);
                    context1.SaveChanges();

                    using (var context2 = new CatsContext(options))
                    {
                        context2.Database.UseTransaction(transaction.GetDbTransaction());
                        context2.Cats.Add(cat);
                    }

                    transaction.Commit();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    transaction.Rollback();
                }
            }
        }
    }

我收到以下错误:

System.InvalidOperationException: ExecuteScalar requires the command to have a transaction when the connection assigned to the command is in a pending local transaction.  The Transaction property of the command has not been initialized.
   at System.Data.SqlClient.SqlCommand.ValidateCommand(Boolean async, String method)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteScalar()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, String executeMethod, IReadOnlyDictionary`2 parameterValues, Boolean openConnection, Boolean closeConnection)
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)

交易范围不是实体框架的一部分。它是 System.Transactions 命名空间的一部分。此外,TransactionScope 不是推荐方法用于使用 Entity Framework 6.x 处理事务。

使用 Entity Framework Core,您只能在关系数据库的多个上下文中共享事务。上下文必须共享相同的数据库连接。

更多信息请点击这里:https://learn.microsoft.com/en-us/ef/core/ saving/transactions#share-connection-and-transaction

Example:

using (var context1 = new YourContext())
{
    using (var transaction = context1.Database.BeginTransaction())
    {
        try
        {
            // your transactional code
            context1.SaveChanges();
            
            using (var context2 = new YourContext())
            {
                // or pass the connection from context1 to the constructor of context2 with proper overload
                context2.Database.SetDbConnection(context1.Database.GetDbConnection());
                context2.Database.UseTransaction(transaction.GetDbTransaction());
                // your transactional code
                context2.SaveChanges();
            }
            
            // Commit transaction if all commands succeed, transaction will auto-rollback when disposed if either commands fails
            transaction.Commit();
        }
        catch (Exception)
        {
            // handle exception
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

上下文之间的事务 的相关文章

随机推荐