在POST调用期间防止数据库中的重复条目

时间:2018-06-18 21:46:00

标签: c# asp.net-core azure-sql-database entity-framework-core

我有一个用Asp Net Core 2.1编写的API(从2.0升级),它由移动应用程序发送的DTO构建实体。 DTO有一个字段" mobileId" (Guid格式)防止移动设备在联机时发送相同的对象(例如在连接问题之后)。

但是这个解决方案看起来效率不高,如下所示:

Database

有4行,而我实际上只想要1行:S我不明白它是如何发生的,因为我在启动时指定:

services.AddScoped<DbContext>(s =>
{
    // code emitted for brevity
});

API本身的代码集中在Handler中,因为我们的API遵循一小部分CQRS模式和&#34; Dispatcher&#34;通过Autofac注册:

public class DispatcherModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<Dispatcher>()
            .As<IDispatcher>()
            .InstancePerDependency();
    }
}

同样适用于在内部使用我们的作用域DbContext的IUnitOfWork

一开始,我检查一个具有相同&#39; mobileId&#39;的实体。数据库中尚未出现:

if (dto.MobileId != null)
{
    Report existingMobileId = await UnitOfWork.Repository<Report>()
                    .GetFirstOrDefaultAsync(qr => qr.MobileId == dto.MobileId);
    if (existingMobileId != null)
    {
        return new Result<object>(new Error(400, $"Report with '{dto.MobileId}' already exists in DB."));
    }
}

你觉得我做错了什么?或者也许我应该添加其他东西? 谢谢你的帮助guyz:)

技术环境: - ASP.NET Core 2.1 - 实体框架核心 - Azure SQL数据库

1 个答案:

答案 0 :(得分:1)

AddScoped意味着将为每个请求创建新的服务实例,因此,如果您同时有多个请求,则在将每个行都写到db之前检查行的存在时,在存储库级别上可能会有某种竞争条件。我建议将此责任放到数据库级别,在mobileId列上应用“唯一”约束。