EF ci consente di definire un vincolo di indice univoco su più proprietà in questo modo:
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;}
}
Questo mi permette di avere una parte con un nome che è unico per una data fabbrica. Ma cosa succede se ho più fabbriche per regione, e per qualche ragione voglio avere una parte con un nome così unico in una regione, non solo una fabbrica. La struttura sarebbe Regione -> Fabbrica -> Parte. Come definirei un indice univoco per una tale condizione poiché Region non è una proprietà diretta di Part?
Modifica: poiché sembra che non sia possibile definire in EF6, sono aperto a farlo direttamente in SQL Server. Qualcuno può per favore farmi sapere come posso farlo in SQL Server?
Voglio avere una parte con un nome unico in una regione, non solo una fabbrica. . . [e] assicurati che Part.Factory.Region.Id sia sempre uguale a Part.Region.Id, non importa quale?
Si crea la chiave di fabbrica (RegionID, FactoryID) e la chiave di Part (RegionID, FactoryID, PartID). Quindi Part fa riferimento a Factory usando una chiave esterna di (RegionID, FactoryID).
Ciò garantirà che RegionID di una parte sia sempre uguale a RegionID della parte della fabbrica.
Quindi, per rendere un Part.Name univoco all'interno di una Regione, aggiungi un indice Unico su Parte (RegionID, Nome).
Lavorando direttamente in SQL Server (o Database SQL di Azure), è possibile creare un indice univoco in una vista indicizzata ed evitare anche di avere una colonna RegionID su Parte. PER ESEMPIO:
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).