EF允许我们在多个属性上定义唯一的索引约束,如下所示:
public class Part
{
public int Id { get; set; }
[Index("IX_Name_Factory", Order = 1, IsUnique = true)]
public string Name {get;set;}
[Required]
public Factory Factory { get; set; }
[ForeignKey("Factory"), Index("IX_Name_Factory", Order = 2, IsUnique = true)]
public int Factory_Id {get;set;}
}
这使我可以拥有一个名称,该名称对于给定的Factory是唯一的。但是,如果我每个区域都有多个工厂,并且由于某种原因,我想让一个部件在整个区域内具有唯一的名称,而不仅仅是工厂。结构将是Region-> Factory-> Part。由于Region不是Part的直接属性,我将如何为这种条件定义唯一索引?
编辑:由于似乎无法在EF6中定义,所以我愿意直接在sql server中进行操作。有人可以让我知道如何在sql server中做到这一点吗?
答案 0 :(得分:1)
您要实现的目标是,Part实体在逻辑上必须知道其所属的Region,因为它的唯一性是由它定义的。那么,为什么不仅仅让Part也具有对Region的引用,并将该关系的键也用作唯一键的一部分呢?
答案 1 :(得分:1)
我想拥有一个在整个地区(而不仅仅是工厂)具有唯一名称的零件。 。 。 [并且]确保Part.Factory.Region.Id始终与Part.Region.Id相同,无论如何?
您输入Factory的密钥(RegionID,FactoryID)和Part的密钥(RegionID,FactoryID,PartID)。因此,Part是使用(RegionID,FactoryID)的外键引用Factory的。
这将确保零件的RegionID始终与零件工厂的RegionID相同。
然后要使Part.Name在区域内唯一,请在Part(RegionID,名称)上添加唯一索引。
直接在SQL Server(或Azure SQL数据库)中工作,可以在indexed view上创建唯一索引,也可以避免在Part上完全具有RegionID列。 EG:
use tempdb
go
drop table if exists Part
drop table if exists Factory
drop table if exists Region
go
create table Region(RegionID int primary key);
create table Factory(FactoryID int primary key, RegionID int references Region);
create table Part(PartID int primary key, FactoryID int references Factory, Name varchar(200));
go
create view vRegionPartName
with schemabinding
as
select r.RegionID, p.Name PartName
from dbo.Region r
join dbo.Factory f
on r.RegionID = f.RegionID
join dbo.Part p
on p.FactoryID = f.FactoryID
go
create unique clustered index pk_vRegionPartName
on vRegionPartName(RegionID,PartName)
go
insert into Region(RegionID) values (1)
insert into Factory(FactoryID,RegionID) values (1,1)
insert into Factory(FactoryID,RegionID) values (2,1)
insert into Part(PartID,FactoryID,Name) values (1,1,'Part1')
insert into Part(PartID,FactoryID,Name) values (2,2,'Part1')
--fails with
--Msg 2601, Level 14, State 1, Line 36
--Cannot insert duplicate key row in object 'dbo.vRegionPartName' with unique index 'pk_vRegionPartName'. The duplicate key value is (1, Part1).