我对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>();
}
}
答案 0 :(得分:1)
感谢大家的帮助。我正在与另一位开发人员交谈,他提供了以下答案,这确实有效。以下是有关该问题的一些其他信息。 NAME_MASTER表保存记录的名称信息,主键为ID_NUM。 ADDRESS_MASTER表包含记录的所有地址,主键为ID_NUM和ADDR_CDE(它们的地址类型为:合法归属永久物,电子邮件,夏季地址等)记录可能没有* LHP(合法归属永久物)地址),但可能有其他地址记录。无论是否存在* LHP地址记录,我们都想拉出NAME_MASTER记录,因此这实际上是连接的另一个条件。以下工作正常,无论ADDRESS_MASTER中是否存在* LHP记录,都会提取NAME_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() { }
}
答案 1 :(得分:0)
在映射中使用fetch="join"
将导致使用左外连接急切加载地址。我认为outer-join="true"
不是有效属性。如果外键无效(即,如果ID_NUM存在但地址表中不存在记录),not-found="ignore"
会阻止NHibernate抛出异常。
因为您已将fetch="join"
设置为急切加载地址,
ISession.Get<ISINameMasterRecord>(id);
将使用左外连接返回对象和地址。如果地址不存在,地址将为null。
可能导致问题的一件事是您已将AD_ID_NUM映射为复合键。这似乎没有必要。