I am using EF6 in my asp.net application, and I have a problem, that is a bit annoying, and I can't seem to figure out a good solution for it.
My code looks like this:
using (var scope = TransactionScopeUtil.RepeatableReadMaxTimeoutRequired())
{
bool hasConflict = await BookingService.HasConflictAsync(newBooking);
if (!hasConflict)
{
await BookingRepository.InsertAsync(newBooking);
return Json(AjaxPayload.Success());
}
else
{
return Json(AjaxPayload.Error());
}
}
// The transaction scope builder:
public static TransactionScope ReadCommittedMaxTimeoutRequired()
{
return new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadCommitted,
Timeout = TransactionManager.MaximumTimeout
}, TransactionScopeAsyncFlowOption.Enabled);
}
The problem is, if two clients push the same booking time, a conflict should be registered. And one of the calls should return a message that the timeslot is already booked. But it doesn't if they hit the server exactly right(with in the same milis). Both bookings are saved without a problem.
I can fix this by doing a Serializable hardcore locking scope, but I am sure there is a better way, and I'm just too blind to see it?
What is best practices in situations like this?