Мне приходится взимать с пользователей ежемесячную плату, и я хочу быть уверен, что не буду взимать с них плату дважды.
Я создал таблицу под названием PlatformFee, которая выглядит так, чтобы проверить, списал ли я с них деньги. Если есть запись с ReceiverId и текущим месяцем (дата в виде 0624), то я не беру комиссию, в противном случае я беру комиссию.
Могу ли я установить ConcurrencyToken как для ReceiverID, так и для Date, чтобы, если другая запись попытается вставить себя, она выдавала DbUpdateConcurrencyException? Как бы я это сделал?
Второй вопрос: нужен ли мне токен параллелизма или уникальный ключ как для ReceiverId, так и для Date? Или оба?
public class PlatformFee : BaseEntity
{
public int ReceiverId { get; set; }
public long Fee { get; set; }
// Use 4 digit as date Ex. MMYY, 0524
public int Date { get; set; }
}
var hasPaidMonthlyFee = await _dbContext.PlatforFee.Where(p => p.ReceiverId == id && p.Date == 0624).Any();
if (hasPaidMonthlyFee == null)
{
try
{
// insert new record into table
_dbContext.PlatformFee.Add(platformFee);
await _dbContext.SaveChangesAsync();
// pay fee and move on
}
catch(DbUpdateConcurrencyException ex)
{
}
}





Токен параллелизма применяется ко всей строке, чтобы указать, была ли строка изменена между моментом чтения исходного состояния и выполнением инструкции обновления, чтобы защититься от одновременных обновлений двумя пользователями или процессами.
Уникальное ограничение для ReceiverID и Date предотвратит вставку/обновление повторяющихся строк до одних и тех же значений, что больше соответствует тому, что вы хотите предотвратить. Это предотвратит обновление существующей строки до существующей комбинации или вставку новой строки с существующей комбинацией.
Однако ваш пример кода немного неверен. Поскольку вы делаете .Any(), ваша проверка должна быть:
if (!hasPaidMonthlyFee)
Поскольку результатом вашего запроса будет True или False, существует ли строка или нет соответственно.
Ограничение уникальности защитит от вставки другой записи другим сеансом/процессом между моментами, когда:
var hasPaidMonthlyFee = await _dbContext.PlatforFee.Where(p => p.ReceiverId == id && p.Date == date).Any();
... выполняется и:
await _dbContext.SaveChangesAsync();
... выполняет. (что должно быть довольно редко)
Создайте уникальный индекс в базе данных. Вставлять. Если это не удается — запись уже была (хорошо, проверьте код ошибки, чтобы убедиться, что это нарушение уникального индекса).