首页 > 解决方案 > 重复键值违反 SaveChangesAsync 上的唯一约束

问题描述

我在控制器中有以下代码

public async Task<IActionResult> Post(string imei)
{
    var device = await _dbContext.Devices.FirstOrDefaultAsync(x => x.Imei == imei);
    if (device == null)
    {
        await _dbContext.Devices.AddAsync(new Device(imei));
        await _dbContext.SaveChangesAsync();
    }
    else
    {
        throw new ConflictException($"Device with IMEI '{imei}' already exists");
    }

    return Ok();
}

很难复制,但有时我得到了

23505:重复键值违反唯一约束“devices_imei_key”

似乎它device是空的,但是当SaveChanges它已经不为空时。我该如何处理它避免使用try...catch?我可以AsNoTacking()用来提高从数据库中读取的能力吗?

标签: c#entity-framework-coreasp.net-core-webapi

解决方案


这是基本的并发,与往常一样,您需要有一个特定的策略来处理并发。您当前使用的方法是不够的,除非您使用信号量对逻辑进行门控,这样一次只能有一个请求通过管道。这避开了并发问题,但显然会对性能产生影响,因为您在应用程序中创建了一个阻塞点。

由于您有唯一的约束,因此您最好的选择是将代码包装在 try/catch 中并实际处理您面临的场景。由于每个 IMEI 应该只有一个条目,因此您可以简单地执行与在 catch 块的 else 块中所做的相同的操作:返回 a ConflictException

对于这个特定问题,除了添加锁或处理异常(使用 try/catch)之外没有其他选择。不管你走多“快”,总是有可能发生并发冲突,你需要处理它。


推荐阅读