首先使用EF代码时,事务在锁定资源上死锁

时间:2012-05-22 21:14:35

标签: entity-framework tsql ef-code-first

我首先使用EF代码。最近我不得不替换以下代码:

User user = userRepository.GetByEmail("some@email.com");

if (user == null)
{
    user = New User { Email = email, CreatedAt = DateTime.Now };

    userRepository.Add(user);
    unitOfWork.Commit();
}

Context.ExecuteSqlCommand("IF NOT EXISTS(SELECT 1 FROM Users WHERE Email = '{0}')
                           INSERT INTO Users(Email, CreatedAt)
                           VALUES ('email', GETDATE())");

这背后的原因是,在尝试添加数千行时,EF花费了很长时间来运行第一段代码。通过将其更改为ExecuteSqlCommand,处理那么多行的时间减少了很多。

我现在看到的问题(到目前为止只发生过两次)是来自数据库的以下消息:事务(进程ID 52)在锁资源上与另一个进程死锁,并被选为死锁牺牲品。重新运行该交易。

我该如何解决这个问题?我的大多数数据访问都是通过EF完成的,除了上面的一些例外。我之前从未在日志中看到过死锁,所以我认为这与查询有关。

我的问题是:

  1. 有没有办法使用No LOCK编写查询?怎么会这样 查询一下?
  2. 有没有办法让EF对某些查询使用NO LOCK?

1 个答案:

答案 0 :(得分:0)

您真正想要的是提前锁定表,而不是阻止锁定。锁定是必要的,以确保在您的命令中的两个语句之间,一些其他进程没有出现并插入相同的用户。 (插入数据时始终需要锁定,因为正在修改物理存储。)

假设这实际上是导致死锁的命令,以下应该解决它,因为它只要求一个独占锁:

Context.ExecuteSqlCommand(“IF NOT EXISTS(SELECT 1 FROM Users WHERE Email ='{0}')                            插入用户(Email,CreatedAt)                            VALUES('email',GETDATE())“);