Sql server 实体框架应该根据少数列的唯一值集检查重复记录,然后添加新记录

Sql server 实体框架应该根据少数列的唯一值集检查重复记录,然后添加新记录,sql-server,entity-framework,concurrency,composite-key,unique-key,Sql Server,Entity Framework,Concurrency,Composite Key,Unique Key,我有一个场景,在这个场景中,不同的客户端通过一些API(有时通过WebJob)触发多个API调用,导致API代码以并发方式触发。 此API代码通过实体框架在SQL中插入记录。由于并发调用,即使存在检查现有记录的条件,该表也允许插入重复记录。当两个调用之间只有几秒钟的差异时,就会发生这种情况 我想在数据库表级别处理这个问题,将复合键[no single column can set as unique]设置为三列的组合,这样SQL就不会允许基于这三列的重复条目 但是,复合键的一列应允许多个非活动记

我有一个场景,在这个场景中,不同的客户端通过一些API(有时通过WebJob)触发多个API调用,导致API代码以并发方式触发。 此API代码通过实体框架在SQL中插入记录。由于并发调用,即使存在检查现有记录的条件,该表也允许插入重复记录。当两个调用之间只有几秒钟的差异时,就会发生这种情况

我想在数据库表级别处理这个问题,将复合键[no single column can set as unique]设置为三列的组合,这样SQL就不会允许基于这三列的重复条目

但是,复合键的一列应允许多个非活动记录,但不应允许两个具有活动记录的条目

下面的例子将详细说明这个问题:

如果CategoryId和CategoryTypeid相同且都处于活动状态,则不允许使用红框记录

应该允许使用绿色方框的记录。因此,如果有多个记录具有相同的CategoryId和CategoryTypeId,则其中只有一个记录应处于活动状态

请帮助了解如何设计解决方案来解决DB端的问题


只是想提出一个想法也不能评论,所以把这个作为一个答案。 也许你应该在整个联盟中走一走

 select distinct categoryID,categoryTypeID,IsActive from Table where IsActive=1
 union all
 select categoryID,CategoryTypeID,IsActive from Table where IsActive=0
这可能对你有帮助

但是,复合键的其中一列应允许多个非活动记录,但 不应允许两个具有活动记录的条目

这里的问题是什么

定义2个索引

1个唯一索引,CategoryId、CategoryTypeId、IsActive=1作为筛选器 1个非唯一索引CategoryId,CategoryTypeId,IsActive=0作为筛选器

完成了

过滤器是大多数人忽略的鲜为人知的索引事实


唯一的保证方法。

通过@TomTom指南,我用下面的SQL语句解决了这个问题

在表上创建了两个非聚集索引,并尝试重新插入重复项,但出现了相应的错误。创建这些索引可确保表中只能存在一条活动记录

--add unique nonclustered filtered index that allows only one active record
CREATE UNIQUE NONCLUSTERED INDEX unique_active_projects
ON TestDuplicates(CategoryId,CategoryTypeId,IsActive)
WHERE IsActive = 1
GO

--add non-unique nonclustered filtered index to allow multiple non-active records
CREATE NONCLUSTERED INDEX nonunique_inactive_projects
ON TestDuplicates(CategoryId,CategoryTypeId,IsActive)
WHERE IsActive = 0
GO

希望这能帮助有类似问题的人

为什么需要存储重复的非活动记录行?似乎它们是另一个关键字段,如时间戳。非活动记录存储用于审计目的。数据设计为软删除。我最初想将这些记录移动到一个单独的审计表中,但现在无法承受所有这些更改。因此,现在必须接受这种情况。查询不是关于获取要读取的记录,而是表的设计应该保持所需的约束,因此,在任何时候都只能插入一条活动记录。我不知道是否可以通过过滤器/索引来实现这一点。请您也详细说明如何通过屏幕截图的步骤实现这一点/以任何详细的方式将其设置为表级。这是否需要ALTERTABLE命令。如果是,在应用此方法之前是否应先截断表?当然可以。每小时90欧元。这是isa问答网站,我不是在那里免费为您提供详细的说明,包括屏幕截图。有一本手册,你知道的。使用它。我给了你足够的提示来找到相关的部分。刚刚节省了90欧元:找到了解决方案,将你的提示作为参考,并通读了很多文章。在此处发布解决方案的实现。非常感谢你给我指引了正确的方向!!这真的很有帮助。