Неполадки отображения Nhibernate с ошибкой вставки дочернего объекта

Я весь день бьюсь головой об стол со следующей проблемой Nhibernate.

Каждый банковский счет имеет один (и только один) набор ставок, связанных с ним. Первичный ключ таблицы банковских счетов BankAccountID также является внешним ключом и первичным ключом в таблице 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; }
}

У меня есть следующие сопоставления HBM для 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>

и следующее для 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>

Существующий объект BankAccount можно без проблем прочитать из базы данных. Однако при создании нового BankAccount оператор вставки завершается неудачно;

Cannot insert the value NULL into column 'BankAccountId'

Проблема заключается в том, что дочерний объект AccountRate создается первым. Поскольку он еще не получил идентификатор от своего родителя, вставка завершается неудачно.

Я думаю, что я правильно сказал, что если бы свойство AccountRate на BankAccount было коллекцией, я мог бы использовать следующее?

Inverse=True

чтобы заставить родителя быть вставленным первым.

Кто-нибудь может мне с этим помочь? Я действительно не хочу использовать коллекцию, между этими таблицами существует только однонаправленное отношение один-к-одному.

Спасибо

Павел

2 ответа

Решение

Хорошо, я думаю, что я исправил проблему. Похоже, что моя проблема - это классическая однозначная связь с общими значениями первичного ключа. Ответ был найден в результате хорошего ночного сна, а затем на странице 192-193 "Nhibernate в действии".

Сначала был ряд ошибок, которые нуждались в исправлении. Это потребовало модификации как классов, так и файлов HBM.

Во-первых, каждый класс должен содержать свойство другого класса, поэтому мне нужно было добавить свойство BankAccount в класс 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; } 
    Public virtual BankAccount BankAccount {get;set;}
} 

Я также сделал ошибку в файле BankAccount HBM, я не должен был делать класс генератора чужим. Это должно было быть в классе AccountRate. Ограничение также необходимо было удалить из связи один-к-одному. Новый файл BankAccount HBM выглядит следующим образом.

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

Затем для AccountRate HBM необходим класс генератора, установленный на чужой, и добавлен тег "один к одному", чтобы завершить отношения между классами.

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

Спасибо всем, кто нашел время, чтобы взглянуть на эту проблему. Я думаю, это все часть кривой.

Павел

Один быстрый способ обойти это - сделать BankAccountId обнуляемым. NHibernate должен вставить запись в таблицу BankAccount с нулевым идентификатором, а затем обновить идентификатор.

В прошлом я наткнулся на способ заставить его делать начальную вставку с правильным идентификатором вместо нуля. К сожалению, я не могу на всю жизнь вспомнить, что я изменил.

Другие вопросы по тегам