2013-02-14 2 views
2

Я немного новичок в NHibernate, и у меня возникла проблема с попыткой присоединиться к двум таблицам. У меня есть таблица имен и адресная таблица. Я хочу вытащить запись названия независимо от того, будут ли возвращены какие-либо результаты для записи адреса. Если у меня есть запись адреса в приведенном ниже коде, но после удаления записи адреса я больше не получаю запись имени. Я пытался это сделать (NHibernate Left Outer Join), но это не работает для меня. Есть идеи?NHibernate Left Outer Join Name to Address

Mapping:

<?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 (юридический домашний постоянный адрес), но могут иметь другие записи адресов. Мы хотели вытащить запись NAME_MASTER независимо от наличия записи адреса LHP, так что это действительно другое условие для соединения. Ниже работает и будет тянуть запись NAME_MASTER независимо от наличия записи * LHP в ADDRESS_MASTER.

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" является допустимым атрибутом. not-found="ignore" предотвращает исключение NHibernate из исключения, если внешний ключ недействителен (то есть, если ID_NUM существует, но запись не существует в таблице адресов).

Потому что вы установили fetch="join" для нетерпеливого нагрузки адрес,

ISession.Get<ISINameMasterRecord>(id); 

возвращает объект и адрес, используя левое внешнее соединение. Адрес будет пустым, если он не существует.

Одна из проблем, которые могут вызывать проблемы, заключается в том, что вы сопоставили AD_ID_NUM в виде составного ключа. Это не представляется необходимым.