Объект ссылается на несохраненную временную проблему экземпляра - PullRequest
1 голос
/ 15 марта 2011

У меня есть экран ввода сотрудника для нового сотрудника, который при отправке перехватывается механизмом связывания модели сотрудника. У сотрудника есть «бизнес-единица» и «переопределить бизнес-единицу». Переопределенная бизнес-единица была недавно добавлена ​​и является причиной моих проблем.

Вот частичное сопоставление сотрудников:

 <class name="Employee" table="Employee">
    <id name="Id" column="id">
      <generator class="native" />
    </id>
    ...
    <many-to-one name="BusinessUnit" class="BusinessUnit" column="businessUnitId" />
    <many-to-one name="OverrideBusinessUnit" class="BusinessUnit" column="overrideBusinessUnitId" not-null="false" />
    ...
   </class>

Вот отображение бизнес-единицы:

<class name="BusinessUnit" table="BusinessUnit" lazy="true">
    <id name="Id" column="id">
        <generator class="native" />
    </id>
    <property name="Description" column="description"/>
    <many-to-one name="guidelineApprover" class="Employee" column="guidelineApproverId" cascade="none" fetch="join" access="field" />
    <many-to-one name="increaseApprover" class="Employee" column="increaseApproverId" cascade="none" fetch="join" access="field" />
 </class>

В подшивке модели сотрудника после отправки формы я использую NHibernate для получения из базы данных как бизнес-единицы, так и переопределенной бизнес-единицы. Это код:

Извлечение бизнес-единицы из базы данных в подшивку модели:

   string attemptedBusinessUnitId = valueProvider.GetValue(key).AttemptedValue;
   Int32.TryParse(attemptedBusinessUnitId, out businessUnitId);
   employee.BusinessUnit = businessUnitRepository.Get(businessUnitId);
   modelState.SetModelValue(key, valueProvider.GetValue(key));

Извлечение переопределенной бизнес-единицы из базы данных в подшивке модели:

    string attemptedOverrideBusinessUnitId = valueProvider.GetValue(key).AttemptedValue;
    Int32.TryParse(attemptedOverrideBusinessUnitId, out overrideBusinessUnitId);
    employee.OverrideBusinessUnit = businessUnitRepository.Get(overrideBusinessUnitId);
    modelState.SetModelValue(key, valueProvider.GetValue(key));

Мой текущий режим извлечения установлен на «принятие». Моя проблема в том, что я начал получать следующую ошибку после того, как добавил «переопределить бизнес-единицу» «многие-к-одному» и попытался выполнить employeeRepository.Save (employee):

    object references an unsaved transient instance - save the transient instance before flushing. 
Type: BusinessUnit, Entity: BusinessUnit

Если я установлю cascade = "all" в этом поле, я получу еще одно подобное исключение, но о необходимости сохранить временный экземпляр типа Employee, entity EmployeeEmpty. Кто-нибудь может сказать мне, взглянув на фрагменты кода, как я могу избежать этого исключения (желательно без использования каскада)?

Edit:

employeeRepository.Save (employee) просто вызывает session.SaveOrUpdate (employee). Поэтому все, что я пытаюсь сделать, это сохранить сотрудника после присвоения ему двух полей бизнес-единицы, которые я извлек из базы данных.

Ответы [ 2 ]

1 голос
/ 17 марта 2011

Извините. Я понял. На самом деле это была проблема со свойствами BusinessUnit в классе Employee. Я использую шаблон нулевого объекта, поэтому я получаю эту ошибку, потому что NHibernate пытается сохранить временный объект типа "BusinessUnit.Empty". Это произошло из-за ошибки в моем коде, вызванной невозможностью правильно конвертировать между BusinessUnit.Empty и null. В любом случае спасибо за помощь.

Это метод, который я использую при реализации шаблона нулевого объекта. Сначала установите access = "field" в свойствах NHibernate в файле сопоставления. Это позволит NHibernate читать значение из закрытой переменной вместо открытого свойства. например,

<many-to-one name="businessUnit" class="BusinessUnit" column="businessUnitId" cascade="none" access="field" />

Тогда сделай что-нибудь подобное в своем классе:

private BusinessUnit businessUnit;
public virtual BusinessUnit BusinessUnit 
{
    get
    {
        if(businessUnit == null)
            return BusinessUnit.Empty;

        return businessUnit;
    }
    set { 
        if (value == BusinessUnit.Empty)
            value = null;

        businessUnit = value;
    }
}

Как видите, закрытой переменной никогда не будет присвоено значение BusinessUnit.Empty. Вместо этого NHibernate всегда будет видеть значение «ноль». Эта модель - то, что исправило мои проблемы. Надеюсь, что это в конечном итоге будет полезно кому-то еще.

0 голосов
/ 15 марта 2011

Если вы создаете нового сотрудника в форме, затем обновляете BusinessUnit и OverrideBusinessUnit, тогда справедливо следующее:

  1. Вам не нужно использовать cascadeType = All, поскольку вам не нужно сохранять экземпляры бизнес-единиц.
  2. Что делает employeeRepository.SaveOrUpdate (employee)? Если он попытается обновить экземпляр сотрудника, вы получите ошибку, как вы упомянули. Попробуйте сохранить этот объект сотрудника.

Если мои предположения неверны, пожалуйста, отправьте больше фрагментов кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...