2

私はNHibernateに少し慣れていませんが、2つのテーブルを結合しようとすると問題が発生しました。名前表と住所表があります。アドレスレコードに結果が返されるかどうかに関係なく、名前レコードをプルしたい。以下のコードにアドレスレコードがある場合は機能しますが、アドレスレコードが削除されると、名前レコードを受信できなくなります。私はこれ(NHibernate Left Outer Join)を試していましたが、うまくいきません。何か案は?

マッピング:

<?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>();
    }
}
4

2 に答える 2

1

Thanks for everyone's help on this. I was speaking with another developer and he provided the following answer, which does work. Here’s some additional information on the issue. The NAME_MASTER table holds the name information for the record with the primary key being ID_NUM. The ADDRESS_MASTER table holds all the addresses for a record with the primary keys being ID_NUM and ADDR_CDE (they type of address it is: legal home permanent, email, summer address, etc.) A record may not have a *LHP (legal home permanent address), but may have other address records. We wanted to pull the NAME_MASTER record regardless of the presence of the *LHP address record, so this is really another condition on the join. Below is working and will pull the NAME_MASTER record regardless of the presence of a *LHP record in 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() { }
    }
于 2013-02-18T15:06:06.023 に答える
0

Using fetch="join" in your mapping will cause the address to be eager loaded with a left outer join. I don't think that outer-join="true" is a valid attribute. The not-found="ignore" prevents NHibernate from throwing an exception if the foreign key is invalid (that is, if ID_NUM exists but the record does not exist in the address table).

Because you have set fetch="join" to eager load the address,

ISession.Get<ISINameMasterRecord>(id);

will return the object and the address using a left outer join. The address will be null if it doesn't exist.

One thing that may be causing problems is that you've mapped AD_ID_NUM as a composite key. This doesn't appear to be necessary.

于 2013-02-15T16:23:34.247 に答える