使用实体框架核心在读取时锁定数据库行

本文关键字:锁定 数据库 读取 实体 框架 核心 | 更新日期: 2023-09-27 17:58:35

如何使用EF Core在读取时锁定行?我使用TransactionScope找到了一个简单的解决方案,但它们似乎不起作用(找不到类)

问题是,当我在线程中删除一个项目,并按下删除按钮两次时,该项目第二次不在那里,所以我得到了一个异常。

我的第一个解决方案是检查项目是否仍然存在,但由于方法被称为task,在两个任务中的任何一个删除它之前,检查都是由两个任务执行的。因此,我需要锁定此行以阻止第二个任务产生错误。

一个快速的解决方案当然是尝试空接,但我更喜欢以干净的方式处理。

使用实体框架核心在读取时锁定数据库行

另一个选项是在删除操作中不使用EF。

如果执行原始SQL DELETE TableName WHERE PrimaryKey = @Key并且记录已被删除,则不会出现错误。


Dapper

    using (var sqlConnection = new System.Data.SqlClient.SqlConnection(Connectionstring))
    {
        sqlConnection.Open();
        string sqlQuery = "DELETE FROM [dbo].[Customer] WHERE CustomerId=@CustomerId";
        sqlConnection.Execute(sqlQuery, new {customerId});
        sqlConnection.Close();
    }

Tortuga链

dataSource.DeleteByKey ( "Customer", CustomerId).Execute();

EF

using (var context = new [...]) {
    context.Database.ExecuteSqlCommand("DELETE FROM [dbo].[Customer] WHERE CustomerId=@CustomerId", new SqlParameter("@CustomerId", CustomerId));
}

(是的,使用EF执行非EF查询是浪费,但这是一种选择。)

在存储过程中编写Delete语句(带有将在Delete stmt的where子句中使用的必要参数),并在EF中调用该存储过程。DB将负责并发性。如果您需要知道存储过程是否删除了任何记录,它可以将受影响的行作为您可以在C#中处理的输出参数返回。

这是传统的,IMHO是最好的方法。

我觉得,无论何时,当您导致INSERT、UPDATE或DELETE时,都应该在try/catch中屏蔽您的ef查询,因为您可以在各种例程条件下触发异常,如外键冲突、找不到记录等。这样的异常应该被视为错误,但不是致命的,因此应该进行处理。那么你的问题的答案不是如何避免异常,而是确保它不会让你感到惊讶。