SQL Server / ADO.Net: сущность с первичным ключом FK, состоящим из нескольких частей, с одной дополнительной частью? - PullRequest
0 голосов
/ 13 марта 2012

Вот вопрос SQL Server / ADO.Net Entity Framework: я ищу «лучший» способ сделать это.

У меня есть иерархическая структура объектов, подобная следующей:

Company -> Division -> Department -> Group -> Specialty

Первичный ключ каждого (кроме Компании) состоит из внешнего ключа, указывающего на PK каждого из его предков.Итак, Specialty выглядит следующим образом:

[PK/FK] CompanyID (string)
[PK/FK] DivisionID (int)
[PK/FK] DepartmentID (int)
[PK/FK] GroupID (int)
[PK]    SpecialtyID (int)
        Name (string)
        Description (string)

Эта базовая структура должна оставаться на месте по причинам, в которые я не буду вдаваться - поэтому, используя GUID, поскольку PK на самом деле отсутствует в картах - мыдолжны взаимодействовать с другими приложениями, использующими конструкцию идентификатора Bergdorf.6.3.4.1, которую отражает эта структура.

Теперь мне нужно добавить возможность добавить специальность, которая применяется квесь отдел, а не группа.Итак, в идеальном мире у нас было бы следующее:

[PK/FK] CompanyID (string)
[PK/FK] DivisionID (int)
[PK/FK] DepartmentID (int)
[PK/FK] GroupID (int/NULL)
[PK]    SpecialtyID (int)
        Name (string)
        Description (string)

... такое, что если GroupID специализации равен нулю, это означает, что он применим ко всему отделу.

НоКонечно, вы не можете иметь пустое поле как часть PK.Так что это не нужно.

Также просто не удастся просто вытащить GroupID из PK, потому что тогда SpecialtyID должен быть уникальным для всего отдела, и мы уже создали идентификаторы, которыесделать это невозможным.

Невозможно создать «специальный» GroupID (например, «-1»), который означает «нет группы», поскольку ограничения FK потребуют от нас создания группы с идентификатором -1для каждого отдела.

... Итак ... что здесь делать правильно?Должен ли я сделать GUID для специальности и вытащить все эти FK из ПК?Очень хотелось бы избежать этого, если это возможно.

Любые идеи будут высоко оценены!

Ответы [ 3 ]

1 голос
/ 14 марта 2012

Я рекомендую иметь две (подтипные) базовые таблицы без обнуляемых столбцов: одну для специальностей отдела и другую для групповых специальностей.Возможно, вам понадобится третья таблица (супертипа) для всех специальностей, чтобы вы могли иметь значения SpecialtyID, которые являются уникальными для всех специальностей независимо от подтипа.

Тогда у вас может быть VIEW, который UNION s объединяет подтипы, и здесь вы можете ввести значение по умолчанию (например, -1) для "пропущенных" GroupID s для специальностей отдела.Вы можете пойти дальше и выставить только VIEW, не открывать базовые таблицы и использовать триггеры INSTEAD OF на VIEW для перемещения обновлений в базовую таблицу.

В любом случае вам потребуется механизм, обеспечивающий, чтобы для каждой созданной специальности (супертипа) также создавалась ровно одна Специальность отдела или Специальности группы, например, вы можете отозвать все разрешения на запись для всех реализованных базовых таблиц.и VIEW s и вынуждают пользователей создавать Specialities, используя кодированные вами процедуры CRUD, чтобы гарантировать, что требования супер / подтипа всегда выполняются.

1 голос
/ 14 марта 2012

Вы можете создать вычисляемый столбец "null-buster", основанный на столбце GroupID, который можно обнулять, и сделать его частью PK вместо GroupID:

create table Specialities (
    CompanyID varchar(10) not null,
    DivisionID int not null,
    DepartmentID int not null,
    GroupID int null,
    SpecialityID int not null,
    Name varchar(10) not null,
    Description varchar(max) not null,
    _NNGroupID as ISNULL(GroupID,-1),
    constraint PK_Specialities PRIMARY KEY (CompanyID,DivisionID,DepartmentID,_NNGroupID,SpecialityID)
)

Я неуверен, нравится ли мне эта идея или нет, но это может быть вариант для вас.Это предполагает, что реального GroupID из -1 никогда не будет - вам, возможно, придется выбрать другое магическое значение для ваших целей.До тех пор, пока значение в правой части ISNULL не является частью домена реальных GroupID s, это должно работать.

Вы по-прежнему будете иметь внешний ключ, определенный для GroupID вместо _NNGroupID, так что обнуляемость ограничения внешнего ключа работает так, как вы ожидаете.

0 голосов
/ 14 марта 2012

Вы можете создать таблицу внешних ссылок, связывающую специальность с отделом: xSpecialtyDepartment(SpecialtyID int, DepartmentID int)

...