2010-05-09 1 views
3

Je me suis cogné la tête contre le bureau toute la journée avec le problème Nhibernate suivant.Nhibernate Problème de mappage un-à-un avec l'erreur d'insertion d'objet enfant

Chaque compte bancaire est associé à un (et un seul) ensemble de débits. La clé primaire de la table de compte bancaire, BankAccountID, est également une clé étrangère et la clé primaire de la table AccountRate.

public class BankAccount 
{ 
    public virtual int BankAccountId { get; set; } 
    public virtual string AccountName { get; set;} 
    public virtual AccountRate AccountRate {get;set;} 
} 

public class AccountRate 
{ 
    public virtual int BankAccountId { get; set; } 
    public virtual decimal Rate1 { get; set; } 
    public virtual decimal Rate2 { get; set; } 
} 

J'ai les correspondances HBM suivantes pour BankAccount:

<class name="BankAccount" table="BankAccount"> 
<id name ="BankAccountId" column="BankAccountId"> 
    <generator class="foreign"> 
    <param name="property"> 
     AccountRate 
    </param> 
    </generator> 
</id> 
<property name ="AccountName" column="AccountName" /> 
<one-to-one name="AccountRate" class="AccountRate" constrained="true" cascade="save-update"/> 
</class> 

et les éléments suivants pour AccountRate:

<class name="AccountRate" table="AccountRate"> 
<id name ="BankAccountId" column="BankAccountId"> 
    <generator class="native" /> 
</id> 
<property name ="Rate1" column="Rate1" /> 
<property name ="Rate2" column="Rate2" /> 
</class> 

Un objet BankAccount existant peut être lu à partir de la base de données sans problème. Cependant, lorsqu'un nouveau compte bancaire est créé, l'instruction d'insertion échoue avec;

Cannot insert the value NULL into column 'BankAccountId' 

Le problème semble être que l'objet enfant, AccountRate est créé en premier. Comme il n'a pas encore reçu d'identifiant de son parent, l'insertion échoue.

Je pense que j'ai raison de dire que si la propriété AccountRate sur BankAccount était une collection, je pourrais utiliser ce qui suit?

Inverse=True 

afin de forcer le parent à être inséré en premier.

Quelqu'un peut-il m'aider avec ceci? Je ne veux vraiment pas utiliser une collection, il n'y a qu'une relation unidirectionnelle un-à-un entre ces tables.

Merci

Paul

Répondre

5

Ok, je pense que j'ai résolu le problème. Il semble que mon problème soit une association un-à-un classique avec des valeurs de clé primaire partagées. La réponse a été trouvée par une bonne nuit de sommeil, puis en se référant à la page 192-193 de 'Nhibernate in Action'.

D'abord, un certain nombre d'erreurs devaient être corrigées. Cela a nécessité une modification des classes et des fichiers HBM. Tout d'abord, chaque classe doit contenir une propriété du type de classe other, donc j'ai dû ajouter une propriété BankAccount à la classe AccountRate. J'ai également fait une erreur dans le fichier BankAccount HBM, je n'aurais pas dû rendre la classe du générateur étrangère. Cela aurait dû être sur la classe AccountRate. La contrainte devait également être supprimée du lien un-à-un. Le nouveau fichier BankAccount HBM est le suivant.

<class name="BankAccount" table="BankAccount"> 
<id name ="BankAccountId" column="BankAccountId"> 
    <generator class="native"> 
</id> 
<property name ="AccountName" column="AccountName" /> 
<one-to-one name="AccountRate" class="AccountRate" cascade="all"/> 
</class> 

Suivant la AccountRate HBM a besoin de la classe groupe électrogène à l'étranger, et une étiquette 'one-to-one', a ajouté pour compléter la relation entre les classes.

<class name="AccountRate" table="AccountRate">   
<id name ="BankAccountId" column="BankAccountId">   
    <generator class="foreign"> 
     <param name="property">BankAccount</param> 
    </generator>   
</id>   
<property name ="Rate1" column="Rate1" />   
<property name ="Rate2" column="Rate2" /> 
<one-to-one name="BankAccount" class="BankAccount" constrained="true" />  
</class> 

Merci à tous ceux qui ont pris le temps de se pencher sur ce problème. Je suppose que tout cela fait partie de la courbe.

Paul

+0

Confirmer que cela fonctionne comme prévu. – Darius

0

Un moyen rapide autour serait de faire le annulable BankAccountId. NHibernate doit insérer un enregistrement dans la table BankAccount avec un ID nul, puis mettre à jour l'ID.

Dans le passé, je suis tombé sur un moyen de faire l'insertion initiale avec l'id correct au lieu de null. Malheureusement, je ne peux pas pour la vie de moi me souviens de ce que j'ai changé.

Questions connexes