【问题标题】:NHibernate Left Outer Join Name to AddressNHibernate 左外连接名称到地址
【发布时间】:2013-02-14 22:18:19
【问题描述】:

我对 NHibernate 有点陌生,我在尝试加入两个表时遇到了问题。我有一个姓名表和地址表。无论地址记录是否返回任何结果,我都想提取名称记录。如果我在下面的代码中有地址记录有效,但是一旦地址记录被删除,我将不再收到姓名记录。我正在尝试这个(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>();
    }
}

【问题讨论】:

    标签: c# nhibernate


    【解决方案1】:

    感谢大家对此的帮助。我正在与另一位开发人员交谈,他提供了以下答案,这确实有效。以下是有关该问题的一些附加信息。 NAME_MASTER 表保存主键为 ID_NUM 的记录的名称信息。 ADDRESS_MASTER 表包含一条记录的所有地址,主键为 ID_NUM 和 ADDR_CDE(它们的地址类型是:合法居住地、电子邮件、夏季地址等)。记录可能没有 *LHP(合法居住地地址),但可能有其他地址记录。无论*LHP 地址记录是否存在,我们都想拉取 NAME_MASTER 记录,所以这实际上是连接的另一个条件。下面正在工作,无论 ADDRESS_MASTER 中是否存在 *LHP 记录,都将提取 NAME_MASTER 记录。

    ma​​ppings.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() { }
        }
    

    【讨论】:

      【解决方案2】:

      在您的映射中使用fetch="join" 将导致地址被急切加载并带有左外连接。我不认为 outer-join="true" 是一个有效的属性。 not-found="ignore" 防止 NHibernate 在外键无效时抛出异常(即如果 ID_NUM 存在但地址表中不存在记录)。

      因为你已经设置了fetch="join" 来预加载地址,

      ISession.Get<ISINameMasterRecord>(id);
      

      将使用左外连接返回对象和地址。如果地址不存在,该地址将为空。

      可能导致问题的一件事是您已将 AD_ID_NUM 映射为复合键。这似乎没有必要。

      【讨论】:

        猜你喜欢
        • 2011-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多