【问题标题】:EF Core does not lock table from readEF Core 不会锁定表以防止读取
【发布时间】:2022-11-16 13:03:37
【问题描述】:

我需要在插入数据之前进行状态检查,但我发现即使我设置了隔离级别,EF Core 也不会锁定表以防止读取。

这是我的代码:我需要锁定SignTicket表和SignTicketApproval表,从读取到提交,这样其他人就不会得到关于票证状态的虚假数据。但即使我设置了隔离级别,我仍然可以在 SSMS 中读取表。

我需要一个表级锁,因为这是一个insert-only表,每次操作都必须检查最新记录以确定ticket的状态。

谢谢你。

using var _context = new EFContext();

using var transaction = _context.Database.BeginTransaction(System.Data.IsolationLevel.Serializable);

var ticket = _context.SignTicket
                     .Include(x => x.SignTicketApproval)
                     .ThenInclude(x => x.Result)
                     .Single(x => x.Id == cancelSignTicketRequest.SignTicketId.ToLong());

if (_signTicketService.GetTicketStatus(ticket) != TicketStatus.Open)
{
    throw new SignTicketStatusException("Ticket status is not open", ticket);
}

// Create new fake approval request and set __Cancel as outcome
var utcNow = DateTime.UtcNow;

var cancelSignoff = new SignTicketApproval()
            {
                AssignedTo = cancelSignTicketRequest.CanceledBy,
                Description = "User cancel",
                CreateTime = utcNow,
                Result = new SignTicketApprovalResult()
                {
                    Canceled = true,
                    ApproverEmail = cancelSignTicketRequest.CanceledBy,
                    CreateTime = utcNow,
                    Outcome = ReservedButton.CancelButton,
                    Comment = cancelSignTicketRequest.Reason
                }
            };

ticket.SignTicketApproval.Add(cancelSignoff);

_context.SaveChanges();
transaction.Commit();

【问题讨论】:

  • 隔离级别不做表锁,它会锁定您读取的行,但同样不会阻止其他事务查询数据或插入新行。 (它可以阻止在指定键并可能在锁定范围内的插入)因此,例如使用可序列化隔离级别,在断点之后尝试对该行进行更新将被阻止,但读取不会,而其他行的更新则不会。当并发很重要时,我建议使用在接受任何更改之前检查的并发时间戳/行版本。

标签: c# .net sql-server entity-framework-core


【解决方案1】:

根据您的代码,

Serializable, Volatile 数据只能读取不能修改,不能新建 数据可以在交易过程中添加。

您可能想尝试 ReadCommitted

易失性数据在交易过程中无法读取,但可以 修改的。

reference

【讨论】:

  • ReadCommitted 仍然不起作用,我在 SaveChange 之前暂停了我的程序,但仍然可以在 SSMS 中对表执行选择。我已经尝试了所有隔离级别,但都没有用。
  • @qwer11121 你试过这样吗using (var txn = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted})) { You read query here }
  • 在 ssms 中使用 DBCC USEROPTIONS 并查看隔离级别。
  • Read Committed 隔离级别不会锁定整个表,实际上是 SQL Server 上的默认隔离级别,如果没有另外指定。
猜你喜欢
  • 2010-11-06
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
相关资源
最近更新 更多