2010-11-30 4 views
0

étrangères J'ai 2 tables comme suit:NHibernate Cartographie d'une table ont été la clé primaire est également une clé

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) 

Chaque utilisateur peut avoir un 0 ou 1 touches externes. Les choses sont configurées de cette façon car l'ajout d'une colonne unique nullable à SQL Server n'autorise pas plus de 1 valeur nulle.

Basé sur Ayende's post, il semble que cela pourrait être géré en utilisant un mappage <one-to-one>. Cependant, cela nécessiterait que la table UserExternalKeys possède sa propre clé primaire.

Le nouveau schéma ressemblerait à quelque chose comme ceci:

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) 

Je pense que cela fonctionnerait, mais il se sent comme je n'ajouterai la colonne UserExternalKeyId pour apaiser NHibernate.

Des suggestions?

+0

Ajouter des colonnes pour apaiser NHibernate est comme un rite de passage. – marr75

Répondre

2

Si un utilisateur peut avoir 0 ou 1 clés externes pourquoi ne pas concevoir les tables comme:

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

et utiliser l'une des solutions de contournement pour ce problème. Si vous utilisez SQL Server 2008, vous pouvez utiliser un filtered index. Si vous utilisez une version antérieure, vous pouvez utiliser un déclencheur, une vue indexée (2005) ou le nullbuster workaround.

Vous pouvez également conserver votre schéma d'origine et mapper la relation entre les utilisateurs et UserExternalKeys. Mapper la collection en tant que membre privé et exposer l'accès à travers une propriété:

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

J'ai eu ce problème dans le passé, mais je n'avais jamais entendu parler de la solution de contournement nullbuster et je n'avais pas pensé à la vue indexée. (J'ai utilisé un déclencheur pour faire ça qui pue un peu). L'index filtré serait le meilleur, mais je suis coincé sur 2005 pour le moment. J'ai fini par utiliser le 2ème schéma et créer une relation plusieurs-à-un entre les utilisateurs et les clés en raison de l'ancien code que je ne voulais pas compliquer. Mais à vrai dire, j'aime mieux vos suggestions :) – dana

Questions connexes