2013-02-14 215 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映射为组合键。这似乎没有必要。