我必须向用户收取月费,并希望确保不会向他们收取两次费用。 所以我创建了一个名为
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
await _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();
...执行。 (应该很少见)