在两列上创建约束以支持特定规则
Posted
技术标签:
【中文标题】在两列上创建约束以支持特定规则【英文标题】:Creating a constraint on two columns to support specific rule 【发布时间】:2018-08-24 14:23:27 【问题描述】:我有一个存储设备详细信息的表。为简单起见,这些列是:
Id (Primary Key)
Name (varchar)
StatusId (Foreign Key to Status table).
Status 表有两列:
Id (Primary Key)
State (varchar)
还有两行:
[Id | State]
1 | Active
2 | Inactive
我想允许设备表中的多个设备具有相同的名称,但在任何时候只有其中一个可以处于活动状态。
也就是说,在Devices表中应该是允许的:
[Id | Name | StatusId]
10 | Mobile001 | 1
11 | Mobile001 | 2
12 | Mobile001 | 2
20 | Tablet001 | 1
21 | Tablet002 | 2
22 | Tablet002 | 1
23 | Tablet003 | 2
但这不应该被允许:
[Id | Name | StatusId]
10 | Mobile001 | 1 <-- wrong
11 | Mobile001 | 1 <-- wrong
12 | Mobile001 | 2
20 | Tablet001 | 1
21 | Tablet002 | 1 <-- wrong
22 | Tablet002 | 1 <-- wrong
23 | Tablet003 | 2
有没有办法在 T-SQL 中创建一个约束来拒绝违反此规则的插入和更新?有没有办法在 EF 代码中首先使用 EntityTypeConfigurations 和 Fluent API,可能通过 IndexAnnotation 或 IndexAttributes 来实现?
谢谢。
【问题讨论】:
使用过滤的唯一索引。 【参考方案1】:正如@ZoharPeled 刚刚评论的那样,一种方法是使用过滤的唯一索引。
由于您只能使用一个特定名称的活动设备,因此可以如下实现:
USE Sandbox;
GO
--Create sample table
CREATE TABLE Device (ID int IDENTITY(1,1),
[name] varchar(10),
[StatusID] int);
--Unique Filtered Index
CREATE UNIQUE INDEX ActiveDevice ON Device ([name], [StatusID]) WHERE StatusID = 1;
GO
INSERT INTO Device ([name], StatusID)
VALUES ('Mobile1', 1); --Works
GO
INSERT INTO Device ([name], StatusID)
VALUES ('Mobile1', 0); --Works
GO
INSERT INTO Device ([name], StatusID)
VALUES ('Mobile2', 1); --Works
GO
INSERT INTO Device ([name], StatusID)
VALUES ('Mobile1', 1); --Fails
GO
UPDATE Device
SET StatusID = 1
WHERE ID = 2; --Also fails
GO
SELECT *
FROM Device;
GO
DROP TABLE Device;
任何问题,请尽管提问。
【讨论】:
【参考方案2】:在 EF CF 中,您可以通过设置唯一索引(如 this answer 中所述)来实现。
modelBuilder.Entity<Device>()
.HasIndex(d => new d.Name, d.StatusId )
.IsUnique();
【讨论】:
以上是关于在两列上创建约束以支持特定规则的主要内容,如果未能解决你的问题,请参考以下文章