1

我首先使用 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?
4

1 回答 1

0

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

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

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

于 2012-09-19T22:54:04.843 回答