首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >插入EF Core 5前的锁表

插入EF Core 5前的锁表
EN

Stack Overflow用户
提问于 2021-05-09 09:13:07
回答 1查看 2K关注 0票数 3

我有以下情况:

  • 用户可以创建具有给定数量的订单(例如:500美元),
  • 对订单总量有一个限制,可以在一天内添加(例如:最多2000美元/天)

目前,在创建新秩序时,这一要求的实现如下:

代码语言:javascript
复制
var newOrder = /* logic for creating the new order */;

var orders = _ordersRepository.GetAllBy(userId, date); // get the orders from the db
var totalAmount = orders.Sum(o => o.Amount); 
if(totalAmount < MaximumAmount) {
  newOrder.IsApproved = true;
}
else {
  newOrder.IsApproved = false;
}

_ordersRepository.Add(newOrder);
_ordersRepository.SaveChanges(); // insert into the db

这种方法的问题在于它不能在以下场景中正确地处理并发插入:

  • 最大订单限制:2000美元
  • 在一秒钟内,用户发送10个请求创建10个新订单,每个

500美元

请求是并发处理的,由于时间很短,在将新订单保存到数据库之前执行当前实现的检查,因此允许创建所有这些订单。最后,用户结束超过最大限制。

我如何解决这个问题,理想情况下不需要多次调用SaveChanges?我使用的是实体框架核心5和Server。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-10 11:19:14

感谢您的意见和建议!

我尝试使用IsolationLevel设置为Serializable的事务,但后来我意识到这会锁定太多的表(问题中的示例是一个虚拟的,实际的实现要复杂得多)。

我同意有时在数据库中使用这种逻辑可能更容易,但是为此添加一个存储过程会破坏当前的一致性,并且很可能会为其他存储过程打开大门。我并不是说存储过程是不好的,只是在我目前的情况下,即使没有存储过程,实现存储过程也会更加困难/更复杂,但我认为,出于一致性的原因,这是值得的。

我最后的解决方案

我已经将流程分成两个步骤,如下所示:

代码语言:javascript
复制
// step 1
var newOrder = /* logic for creating the new order */;
_ordersRepository.Add(newOrder);
_ordersRepository.SaveChanges(); // insert into the db

// step 2
var orders = _ordersRepository.GetAllBy(userId, date); // get the orders from the db
var totalAmount = orders.Sum(o => o.Amount); 
if(totalAmount < MaximumAmount) {
  newOrder.IsApproved = true;
}
_ordersRepository.Update(newOrder); 
_ordersRepository.SaveChanges(); // update the new order

false.

  • Step

  • 步骤1只是创建新的订单并将其插入到数据库中,将IsApproved标志留给默认的

  • 2执行每日限制验证,如果检查通过,则IsApproved标志将传递给true.

我知道这不是一个真正的解决方案,而是一个解决办法。锁定一个表可能会产生太大的性能影响,特别是如果给定的表被多个应用程序功能所使用。使用此解决方案,即使步骤2中有问题,订单也将留给IsApproved=false,因此不会产生任何影响,用户可以稍后再试,或者支持人员可以处理它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67456042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档