一对多验证竞争条件

One-to-many validation race condition

我有两个具有一对多关系的实体。

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中添加用户时存在竞争条件。接下来,在流A中添加具有相同UserId的用户。

我尝试使用 ConcurrencyCheck 属性,并且正在考虑 TripRequest 的复合键。 是否可以在数据库端进行此类检查?解决此问题的最佳方法是什么?

您不应该将此视为并发问题,因为您可以使用唯一的 constraint/unique 索引来绝对防止有两个 TripRequests 用于相同的 (TripId,UserId),例如:

[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; }
}