我遇到了一个问题,这个问题暴露了我对唯一性约束的不了解。这是有问题的表格,表格的DataManagerId
,SurgeonId
和HospitalId
列上有一个唯一的非聚集索引,如此图所示(道歉,我不知道没有Visio):
我正在使用实体框架(“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中执行多列约束的方式。
谢谢