c# - 一对多验证竞争条件
问题描述
我有两个具有一对多关系的实体。
TripRequest.cs
public class TripRequest
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public User User { get; set; }
public Guid TripId { get; set; }
public Trip Trip { get; set; }
}
Trip.cs
public class Trip
{
public Guid Id { get; set; }
public ICollection <TripRequest> Requests { get; set; } = new List<TripRequest>();
}
而且我有一个命令,我想在其中检查行程是否不包含来自用户的其他请求。
public void Handle(CreateRequestCommand command)
{
var trip = _tripRepository.GetWithInclude(t => t.Requests)
.FirstOrDefault(x => x.Id.Equals(command.TripId));
if (trip == null)
{
throw new EntityNotFoundException();
}
if (trip.Requests.Any(x => x.UserId.Equals(command.UserId)))
{
throw new ConflictException();
}
var request = new TripRequest
{
TripId = command.TripId,
UserId = command.UserId,
CreationDate = DateTime.Now
};
_requestRepository.Create(request);
}
当检查在流 A 中通过并且用户被添加到流 B 中时,存在竞争条件。接下来,具有相同 UserId 的用户被添加到流 A 中。
我尝试使用 ConcurrencyCheck 属性,并且正在考虑 TripRequest 的复合键。是否可以在数据库端进行此类检查?解决此问题的最佳方法是什么?
解决方案
您不应该将此视为并发问题,因为您可以使用唯一约束/唯一索引来绝对防止同一(TripId,UserId)有两个 TripRequest,例如:
[Index("UserId","TripId",IsUnique = true)]
public class TripRequest
{
public Guid Id { get; set; }
public Guid UserId { get; set; }
public User User { get; set; }
public Guid TripId { get; set; }
public Trip Trip { get; set; }
}
推荐阅读
- javascript - 事件声明中是否需要“function()”?
- string - 基于字符串评估创建新的位列
- hyperledger-fabric - Hyperledger Fabric 中orderer genesis block 的重要性是什么?
- excel - 从单元格引用中获取文件名和路径
- ilog - 为决策表中创建的新行生成 ID(用户不可编辑)
- javascript - 如何在 NodeJS 中使用 IMAP 通过 messageId 获取电子邮件线程?
- amazon-web-services - S3 和大文件备份
- c# - 当参数类型是基类时将派生类传递给方法
- mercurial - 水银复制
- sql-server - 从xml文件T-sql中读取数据