如何在 EF Core 中的数据库表中的多个列上创建并发令牌检查?

问题描述 投票:0回答:1

我必须向用户收取月费,并希望确保不会向他们收取两次费用。 所以我创建了一个名为

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) {

   }
}
c# .net concurrency entity-framework-core database-concurrency
1个回答
0
投票

将并发令牌应用于整行,以告知在读取初始状态和运行更新语句之间是否已更改行,以防止两个用户或进程并发更新。

对 ReceiverID 和 Date 的唯一约束将防止重复行被插入/更新为相同的值,这听起来更符合您想要防止的情况。这将阻止现有行更新为现有组合或使用现有组合插入新行。

您的代码示例有点不正确。既然您正在做

.Any()
那么您的检查应该是:

if (!hasPaidMonthlyFee)

因为查询的结果将分别是

True
False
是否存在一行。

唯一约束将防止在以下时间之间由另一个会话/进程插入另一条记录:

var hasPaidMonthlyFee = await _dbContext.PlatforFee.Where(p => p.ReceiverId == id && p.Date == date).Any();

...执行并且:

await _dbContext.SaveChangesAsync();

...执行。 (应该很少见)

© www.soinside.com 2019 - 2024. All rights reserved.