2013-02-14 433 views
2

我對NHibernate有點新,我遇到了試圖連接兩個表的問題。我有一個名稱表和地址表。無論地址記錄是否返回任何結果,我都想要取得名稱記錄。如果我在下面的代碼中有地址記錄,但一旦地址記錄被刪除,我不再收到名稱記錄。我正在嘗試這個(NHibernate Left Outer Join),但它不適合我。有任何想法嗎?NHibernate左外部加入名稱地址

映射:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping 
    xmlns="urn:nhibernate-mapping-2.2" 
    namespace="Portlet.IncomingStudentInfo.Data.BusinessObjects" 
    assembly="Portlet.IncomingStudentInfo"> 
    <class name="ISINameMasterRecord" table="NAME_MASTER"> 
     <id name="NM_ID_NUM" column="ID_NUM" type="Int32"> 
      <generator class="native" /> 
     </id> 
     <property name="NM_ID_NUM" column="ID_NUM" /> 
     <property name="NM_EMAIL_ADDRESS" column="EMAIL_ADDRESS" /> 
     <property name="NM_MOBILE_PHONE" column="MOBILE_PHONE" /> 
     <many-to-one name="LHP" class="ISILHPAddress" 
      column="ID_NUM" fetch="join" 
      foreign-key="ID_NUM" 
      outer-join="true" not-found="ignore" /> 
    </class> 

    <class name="ISILHPAddress" table="ADDRESS_MASTER"> 
     <composite-id> 
      <key-property name="AD_ID_NUM" column="ID_NUM" type="Int32" /> 
     </composite-id> 
     <property name="AD_ID_NUM" column="ID_NUM" /> 
     <property name="AD_ADDR_CDE" column="ADDR_CDE" /> 
     <property name="AD_ADDRESS" column="ADDR_LINE_1" /> 
     <property name="AD_CITY" column="CITY" /> 
     <property name="AD_STATE" column="STATE" /> 
     <property name="AD_ZIP" column="ZIP" /> 
     <property name="AD_PHONE" column="PHONE" /> 
    </class> 
</hibernate-mapping> 

門面:

public class ISINameMasterRecordFacade : JICSBaseFacade<ISINameMasterRecord> 
{ 
    public ISINameMasterRecord FindIDCriteria(int id) 
    { 
     ICriteria criteria = this.CreateCriteria(); 
     criteria.Add(Expression.Eq("NM_ID_NUM", id)); 

     criteria.CreateAlias(
      "LHP", 
      "lhp", 
      NHibernate.SqlCommand.JoinType.LeftOuterJoin); 
     criteria.Add(
      Expression.Or(
       Expression.IsNull("lhp.AD_ADDR_CDE"), 
       Expression.Eq("lhp.AD_ADDR_CDE", "*LHP"))); 


     return criteria.UniqueResult<ISINameMasterRecord>(); 
    } 
} 

回答

1

感謝大家的幫助。我與另一位開發人員進行了交談,他提供了以下答案,這確實起作用。以下是關於此問題的其他信息。 NAME_MASTER表保存主鍵爲ID_NUM的記錄的名稱信息。 ADDRESS_MASTER表保存主鍵爲ID_NUM和ADDR_CDE的記錄的所有地址(它們的地址類型爲:合法家庭常駐,電子郵件,夏令時地址等)記錄可能沒有* LHP(合法家庭永久地址),但可能有其他地址記錄。無論是否存在* LHP地址記錄,我們都希望取得NAME_MASTER記錄,所以這實際上是加入的另一個條件。下面是工作,並將拉動NAME_MASTER記錄,無論在ADDRESS_MASTER中存在* LHP記錄。

mappings.hbm.xml

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Portlet.IncomingStudentInfo.Data.BusinessObjects" assembly="Portlet.IncomingStudentInfo"> 
    <class name="ISINameMasterRecord" table="NAME_MASTER"> 
    <id name="NM_ID_NUM" column="ID_NUM" type="Int32"> 
     <generator class="native" /> 
    </id> 
    <property name="NM_ID_NUM" column="ID_NUM" /> 
    <property name="NM_EMAIL_ADDRESS" column="EMAIL_ADDRESS" /> 
    <property name="NM_MOBILE_PHONE" column="MOBILE_PHONE" /> 

    <bag name="Addresses" cascade="all" where="ADDR_CDE='*LHP'" lazy="false" fetch="join"> 
     <key column="ID_NUM"/> 
     <one-to-many class="ISILHPAddress"/> 
    </bag> 
    </class> 


    <class name="ISILHPAddress" table="ADDRESS_MASTER" lazy="false"> 
    <id name="AD_ID_NUM" column="ID_NUM" type="Int32"> 
     <generator class="native" /> 
    </id> 
    <property name="AD_ID_NUM" column="ID_NUM" /> 
    <property name="AD_ADDR_CDE" column="ADDR_CDE" /> 

    <property name="AD_ADDRESS" column="ADDR_LINE_1" /> 
    <property name="AD_CITY" column="CITY" /> 
    <property name="AD_STATE" column="STATE" /> 
    <property name="AD_ZIP" column="ZIP" /> 
    <property name="AD_PHONE" column="PHONE" /> 
    </class> 

</hibernate-mapping> 

ISINameMasterRecordFacade.cs

public ISINameMasterRecord FindIDCriteria(int id) 
     { 
      ICriteria criteria = this.CreateCriteria(); 
      criteria.Add(Expression.Eq("NM_ID_NUM", id)); 

      return criteria.UniqueResult<ISINameMasterRecord>(); 
     } 

ISINameMasterRecord.cs

public class ISINameMasterRecord : EXBase 
    { 
     public virtual int NM_ID_NUM { get; set; } 
     public virtual String NM_EMAIL_ADDRESS { get; set; } 
     public virtual String NM_MOBILE_PHONE { get; set; } 

     public virtual ISILHPAddress LHP 
     { 
      get { return Addresses != null && Addresses.Any() ? Addresses[0] : null; } 
      set 
      { 
       if (Addresses == null) 
        Addresses = new List<ISILHPAddress>(); 

       if (Addresses.Any()) 
        Addresses[0] = value; 
       else 
        Addresses.Add(value); 
      } 
     } 

     //for mapping purposes 
     protected virtual IList<ISILHPAddress> Addresses { get; set; } 


     public ISINameMasterRecord() 
     { 

     } 
    } 

ISILHPAddress.cs

public class ISILHPAddress : EXBase 
    { 
     public virtual int AD_ID_NUM { get; set; } 
     public virtual String AD_ADDR_CDE { get; set; } 
     public virtual String AD_ADDRESS { get; set; } 
     public virtual String AD_CITY { get; set; } 
     public virtual String AD_STATE { get; set; } 
     public virtual String AD_ZIP { get; set; } 
     public virtual String AD_PHONE { get; set; } 

     public ISILHPAddress() { } 
    } 
0

使用在映射fetch="join"將導致地址渴望裝載了左外連接。我不認爲outer-join="true"是一個有效的屬性。如果外鍵無效(也就是說,如果ID_NUM存在但地址表中不存在該記錄),則not-found="ignore"可防止NHibernate拋出異常。

因爲你已經設置fetch="join"躍躍欲試負載地址,

ISession.Get<ISINameMasterRecord>(id); 

將返回對象,並使用左外連接的地址。如果地址不存在,地址將爲空。

可能導致問題的一件事是,您已將AD_ID_NUM映射爲組合鍵。這似乎沒有必要。