实体框架事务和死锁

Posted

技术标签:

【中文标题】实体框架事务和死锁【英文标题】:Entity Framework Transactions and Deadlock 【发布时间】:2016-05-08 00:45:22 【问题描述】:

在上下文中调用 SaveChanges() 时,所有插入/删除/更新操作都在单个事务中执行。也可以将 DbContextTransaction 用于事务。我正在尝试使用这两种方法来模拟死锁。当我使用 DbContextTransaction 时,我会立即得到死锁异常,但即使在一小时后,单独的 SaveChanges() 也不会引发任何死锁异常。我做错了吗?

这是带有 DbContextTransaction 的代码。我尝试更新主线程中的第一行,然后是第二行。我还开始了另一个任务,它尝试先更新第二行,然后再更新第一行。

        while (true)
        
            using (var context = new SchoolDBEntities())
            
                using (System.Data.Entity.DbContextTransaction dbTran = context.Database.BeginTransaction())
                
                    Random r = new Random();
                    int r1 = r.Next();
                    int r2 = r.Next();

                    Student std1 = context.Students.First();
                    std1.StudentName = "test"+r1;
                    context.SaveChanges();

                    Student std2 = context.Students.Find(2);
                    std2.StudentName = "test"+r2;
                    context.SaveChanges();

                    dbTran.Commit();

                

            
        

但是当我尝试使用 SaveChanges() 时,它不会产生死锁:

        while (true)
        
            using (var context = new SchoolDBEntities())
            
                try
                
                    Random r = new Random();
                    int r1 = r.Next();
                    int r2 = r.Next();

                    Student std1 = context.Students.First();
                    std1.StudentName = "test" + r1;
                    Student std2 = context.Students.Find(2);
                    std2.StudentName = "test" + r2;

                    context.SaveChanges();
                
            
        

我正在使用 SQL Profiler 来跟踪事务。我什至为第二种方法添加了更多更新,只是为了使该事务的持续时间等于 DbContextTransaction 案例,我认为这可能是原因,但仍然没有运气!当我查看跟踪时,我看到属于特定事务的更新仅在前一个事务提交后才开始。可能是什么原因?

【问题讨论】:

【参考方案1】:

经过进一步调查,我发现无论我在上下文中所做的更改顺序如何,SaveChanges() 方法始终向 SQL Server 发送更新查询的顺序是基于表的主键的。换句话说,即使我尝试通过首先更改第 2 行然后第 1 行来反转更新请求的顺序,SaveChanges() 首先对第 1 行执行更新查询,然后对第 2 行执行。这就是为什么我没有得到仅使用 SaveChanges() 方法导致死锁。它不会颠倒查询的顺序。

【讨论】:

以上是关于实体框架事务和死锁的主要内容,如果未能解决你的问题,请参考以下文章

实体框架 - SaveChanges 与事务

如何在原始查询中使用实体框架事务?

实体框架事务锁定

事务复制活动时实体框架模型的问题

实体框架和经典 Ado.net 之间的单个事务或批量插入操作下的 SqlBulkCopy 多个表插入

来自实体框架的 SqlException - 不允许新事务,因为会话中正在运行其他线程