2011-03-15 63 views
1

我有一個新員工的員工輸入屏幕,在提交時被員工模型綁定器攔截。員工擁有「業務部門」和「業務部門」。越控業務部門是最近添加的,並且是我的問題的原因。對象引用一個未保存的瞬態實例問題

這裏是部分員工的映射:

<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(員工):

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

如果我設置級聯= 「all」這個字段,我只是得到另一個類似的異常,但是需要保存Employee類型的實例EmployeeEmpty的臨時實例。任何人都可以通過查看代碼片段告訴我如何避免此異常(最好不涉及級聯)?

編輯:

employeeRepository.Save(員工)只是調用session.SaveOrUpdate(員工)。所以我所要做的就是在分配給它之後保存員工,這是我從數據庫中檢索到的兩個業務單位字段。

回答

1

對不起。我想到了。這實際上是Employee類中BusinessUnit屬性的一個問題。我使用空對象模式,所以我得到這個錯誤,因爲NHibernate試圖保存類型爲「BusinessUnit.Empty」的瞬態對象。這是由於未能在BusinessUnit.Empty和null之間正確轉換導致我的代碼中存在錯誤。無論如何感謝所有的幫助。

這是我在實現空對象模式時使用的方法。首先在映射文件的NHibernate屬性中設置access =「field」。這將允許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總是會看到值「null」。這種模式解決了我的問題。希望它最終對別人有幫助。

0

如果要創建形式新員工,然後更新BusinessUnit和OverrideBusinessUnit,然後滿足以下條件:

  1. 您DONOT需要使用的CascadeType =所有,因爲你是DONOT需要保存商業單位的實例。
  2. employeeRepository.SaveOrUpdate(employee)是做什麼的?如果它試圖更新員工實例,那麼您將會看到您提到的錯誤。您應該嘗試保存此員工對象。

如果我的假設錯了,請發佈更多的代碼片段。

+0

我加了一點信息。這對於同一個班級有兩對多的關係,這兩個都是從數據庫中重新水化並分配給該員工的。當我剛剛處理「businessUnit」多對一時,我沒有這個問題。此問題僅在我多次添加「businessUnitOverride」時引入。 – SideFX

+0

我不認爲這可能是一個問題,在映射意義上看起來不錯。但從設計意義上來說,對同一班級的多對多映射並不是一個好主意。既然他們已經很多,爲什麼你想要然後在兩個單獨的名單? –

+0

此外,映射相當混亂。從映射文件中,我可以看到員工和業務單位之間存在多對多關係(準則申請者和增加申請者)。我會建議您再次修改映射,即使您設法在不這樣做的情況下襬脫此錯誤,最終可能會導致問題。在這種情況下,您可能需要GuidelineApprover和IncreaseApprover來擴展Employee,然後使用BussinessUnit進行多對多映射。對於bussinessUnit和overrideBussinessUnit,Employee端應該做同樣的事情。 –

相關問題