EF Update声明违反了唯一索引

时间:2018-01-01 23:40:24

标签: sql sql-server entity-framework entity-framework-core

我遇到了一个问题,这个问题暴露了我对唯一性约束的不了解。这是有问题的表格,表格的DataManagerIdSurgeonIdHospitalId列上有一个唯一的非聚集索引,如此图所示(道歉,我不知道没有Visio):

enter image description here

我正在使用实体框架(“EF”)并且它已生成类似于此的UPDATE语句:

exec sp_executesql N'UPDATE [dbo].[DataManagerSurgeon]
SET [DataManagerId] = @0, [SurgeonId] = @1, [HospitalId] = @2, [DateAdded] = @3, [DateRescinded] = @4
WHERE ([Id] = @5)',N'@0 int,@1 int,@2 int,@3 datetime2(7),@4 datetime2(7),@5 int',@0=24,@1=221,@2=10001,@3='2018-01-02 08:58:29.1061413',@4='2018-01-02 08:58:29.1061413',@5=122

为了这个问题的目的,我会稍微清理一下:

UPDATE [dbo].[DataManagerSurgeon]
SET [DataManagerId] = 24, [SurgeonId] = 221, [HospitalId] = 10001, [DateAdded] = '2018-01-02 08:58:29.1061413', [DateRescinded] = '2018-01-02 08:58:29.1061413'
WHERE [Id] = 122

问题是,这是在寻求改变数据(因此更新声明)。 (DataManagerId,HospitalId,SurgeonId)组合(24,221,10001)已有一行。结果,数据库没有:

Violation of UNIQUE KEY constraint 'UC_ManagerSurgeonHospital'. Cannot insert duplicate key in object 'dbo.DataManagerSurgeon'. The duplicate key value is (24, 221, 10001).

作为进一步的背景,我只是尝试更新DateRescinded列,如果我要手动编写语句,它将如下所示:

UPDATE [dbo].[DataManagerSurgeon]
SET [DateRescinded] = '2018-01-02 08:58:29.1061413'
WHERE [Id] = 122

我想我了解到你可以用UPDATE语句违反唯一性约束,即使按主键识别行也是这样的,即在事务结束时,仍然会满足唯一性约束的条件。 。

但我的问题仍然存在,如果EF正在生成违反唯一性约束(索引)的UPDATE语句,我该如何解决这个问题呢?注意:最不理想的解决方案是编写手动SQL并将其发送到数据库。它可以完成,但是无法使用像EF这样的ORM。

另请注意,我在该表的映射文件中添加了以下代码,以使EF“了解”索引:

        this.HasIndex(t => new { t.DataManagerId, t.SurgeonId, t.HospitalId })
            .IsUnique(true)
            .IsClustered(false)
            .HasName("UC_ManagerSurgeonHospital");

最终附录 - 我一直将此称为索引,我不确定SQL Server如何将这些与CONSTRAINTS区分开来,但这样的索引的create语句如下所示:

ALTER TABLE [dbo].[DataManagerSurgeon] ADD  CONSTRAINT [UC_ManagerSurgeonHospital] UNIQUE NONCLUSTERED 
(
    [DataManagerId] ASC,
    [SurgeonId] ASC,
    [HospitalId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

我只提到这一点,因为人们可能会问为什么我将它作为索引而不是CONSTRAINT实现。但显然,这就是您在SQL Server中执行多列约束的方式。

谢谢

0 个答案:

没有答案