为什么我的上下文不使用我告诉它与context.Database.UseTransaction()一起使用的事务?

时间:2018-12-26 20:37:18

标签: c# transactions entity-framework-6 dapper

很久以前,我们的系统是采用悲观锁定设计的,即在对属于该父对象的任何数据库对象执行任何工作之前,将锁定父对象的行,因此在该对象上只有一个进程可以对该对象进行操作时间。

我需要对一组子对象进行许多复杂的工作,这些子对象可以分为多个部分,每个部分可能成功或失败。为了简化这一点,我有一个连接在父记录上获得了一个锁,然后第二个连接完成了实际的工作,根据需要提交或回滚了每个块。这样可以节省连接工作,而不必在每次完成事务时都必须重新获取锁(并且有可能将该锁丢失给另一个进程)。

所有工作完成后,我想对锁定连接上的锁定父记录进行快速更新。我正在使用Dapper来获取锁定,并使用EF来更新锁定的记录。

但是,当我告诉EF SaveChanges()时,我得到EntityException:“在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常。”内部例外是InvalidOperationException:“连接已经是本地或分布式事务的一部分”。显然,EF忽略了我告诉它使用的ADO事务,并试图以常规方式创建自己的事务。我在做什么错了?

问题区域的简化版本(错误处理和其他似乎与此问题无关的代码已被省略):

public async Task DoWork(long id)
{
    using (var transaction = _connection.BeginTransaction())
    {
        await _connection.QueryAsync(LockStatement, new { id }, transaction);

        // do relevant work in 2nd connection

        using (var context = new MyContext(_connection))
        {
            var parent = await context.MyEntities.FindAsync(id);
            parent.SomeProperty = newValue;
            context.SaveChanges();
        }

        transaction.Commit();
    }
}

我的上下文如下:

public class MyContext : DbContext
{
    public MyContext(DbConnection connection)
        : base(connection, false)
    {
        Configuration.ValidateOnSaveEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }

    public DbSet<MyEntity> MyEntities { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        Database.SetInitializer<MyContext>(null);
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Configurations.Add(new MyEntityConfiguration());
        modelBuilder.HasDefaultSchema(string.Empty);
    }
}

使用Dapper进行读取,使用EF进行写入对我们来说是非常标准的,并且已经运行了一段时间。这是我们第一次尝试通过EF使用较大的事务,而不是每次保存更改时都让它创建新事务。

0 个答案:

没有答案