Как определить многоуровневое ограничение уникального индекса в EF6 - PullRequest
0 голосов
/ 04 февраля 2019

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;}
}

Это позволяет мне иметь деталь с именем, уникальным для данной фабрики.Но что, если у меня есть несколько фабрик на регион, и по какой-то причине я хочу иметь деталь с уникальным для региона именем, а не просто фабрикой.Структура будет Регион -> Фабрика -> Часть.Как бы я определил уникальный индекс для такого условия, поскольку Region не является прямым свойством Part?

Редактировать: так как кажется, что это невозможно определить в EF6, я открыт для этого вSQL Server напрямую.Может кто-нибудь, пожалуйста, дайте мне знать, как я могу сделать это на сервере SQL?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Я хочу иметь деталь с уникальным именем для региона, а не только для фабрики.,,[и] убедитесь, что Part.Factory.Region.Id всегда совпадает с Part.Region.Id, несмотря ни на что?

Вы делаете ключ Factory (RegionID, FactoryID) и ключ Part (RegionID, FactoryID, PartID).Таким образом, Часть относится к Фабрике с использованием внешнего ключа (RegionID, FactoryID).

Это гарантирует, что RegionID Части всегда совпадает с RegionID Фабрики детали.

Затем, чтобы сделать Part.Name уникальным в пределах региона, добавьте уникальный индекс для детали (RegionID, Name).

Работая непосредственно с SQL Server (или базой данных SQL Azure), вы можетесоздайте уникальный индекс в индексированном представлении , а также вообще не используйте столбец 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).
0 голосов
/ 04 февраля 2019

То, что вы пытаетесь достичь, означает, что сущность Part должна логически знать о Регионе, которому она принадлежит, потому что она определяет ее уникальность.Так почему бы не сделать так, чтобы Part тоже имел ссылку на Region, и использовать ключ этого отношения как часть вашего уникального ключа?

...