2010-11-30 2 views
0
иностранных

У меня есть 2 таблицы следующим образом:NHibernate Mapping за столом Были Первичный ключ также является ключевым

create table Users 
(
UserId int primary key identity not null 
) 

create table UserExternalKeys 
(
UserIdRef int primary key not null, 
ExternalKey varchar(50) unique not null 
) 

alter table UserExternalKeys 
add constraint fk_UsersExternalKeys_Users 
foreign key (UserIdRef) 
references Users (UserId) 

Каждый пользователь может иметь 0 или 1 внешние ключи. Вещи настраиваются таким образом, потому что добавление уникального столбца с нулевым значением в SQL Server не допускает более 1 нулевого значения.

На основании Ayende's post, похоже, что это может быть обработано с использованием отображения <one-to-one>. Однако для этого требуется, чтобы таблица UserExternalKeys имела свой собственный первичный ключ.

Новая схема будет выглядеть примерно так:

create table Users 
(
    UserId int primary key identity not null, 
    ExternalKeyRef int null 
) 

create table UserExternalKeys 
(
    UserExternalKeyId int primary key identity not null, 
    ExternalKey varchar(50) unique not null 
) 

alter table Users 
add constraint fk_Users_UsersExternalKeys 
foreign key (ExternalKeyRef) 
references UserExternalKeys (UserExternalKeyId) 

Я думаю, что это будет работать, но он чувствует, как я бы добавлять только UserExternalKeyId колонку, чтобы успокоить NHibernate.

Любые предложения?

+0

Добавление столбцов только для успокоения NHibernate - это как обряд посвящения. – marr75 2010-11-30 21:15:53

ответ

2

Если пользователь может иметь 0 или 1 внешние ключи, почему не дизайн таблицы как:

create table Users 
(
    UserId int primary key identity not null 
    ExternalKey varchar(50) null 
) 

и использовать один из известных способов решения этой проблемы. Если вы используете SQL Server 2008, вы можете использовать filtered index. Если вы используете более раннюю версию, вы можете использовать триггер, индексированное представление (2005) или nullbuster workaround.

Вы также можете сохранить исходную схему и сопоставить отношения как «один ко многим» от пользователей к UserExternalKeys. Составьте коллекцию в качестве частного участника и предоставите доступ к ней через недвижимость:

private IList<UserExternalKeys> _externalKeys; 

public string ExternalKeys 
{ 
    get 
    { 
     if (_externalKeys.Count() == 1) 
     { 
      return _externalKeys.ElementAt(0).ExternalKey; 
     } 
     else 
     { 
      // return null or empty string if count = 0, throw exception if > 1 
     } 
    } 
    set 
    { 
     if (_externalKeys.Count() == 0) { // add key and set value } 
     else { // set value if count = 1, throw exception if > 1 } 
    } 
} 
+0

У меня была эта проблема в прошлом, но я никогда не слышал об обходном пути nullbuster и не думал об индексированном представлении. (Я использовал триггер для этого, который воняет). Отфильтрованный индекс был бы лучшим, но я застрял в 2005 году. Я закончил использовать вторую схему и создал отношения «один-к-одному» от «Пользователи к ключам» из-за некоторого устаревшего кода, с которым я не хотел шуметь. Но, честно говоря, мне нравятся некоторые из ваших предложений лучше :) – dana 2010-12-01 23:47:07

Смежные вопросы