我在我的最新项目中使用了nHibernate并成功映射了所有基本关系,其中值存在于我正在使用的主表中,或者通过简单的关系(如复合)。
我遇到的问题是如何映射复杂的连接?
例如,我有一个名为Contact
的实体,每个contact
都有你常用的属性,如姓名,DOB,电话....但我还需要它有一个名为AccreditationList
的属性这将是List<Accreditation>
。
以下是Contact XML声明的示例。
<class name="Contact" table="Contact" lazy="true">
<id name="ID" column="ContactID" type="guid">
<generator class="guid" />
</id>
<property name="FirstName">
<column name="FirstName" sql-type="nvarchar(500)" not-null="true" />
</property>
<property name="LastName">
<column name="LastName" sql-type="nvarchar(500)" not-null="true" />
</property>
<bag name="AccreditationList" lazy="true">
//How do I express the relationship here?
</bag>
</class>
List<Accreditation>
只能通过这样的一系列连接来确定。
SELECT Accreditation.* FROM CourseEnrolment
INNER JOIN Course ON Course.CourseID = CourseEnrolment.CourseID
INNER JOIN CourseType ON CourseType.CourseTypeID = Course.CourseTypeID
INNER JOIN Accreditation ON Accreditation.AccreditationID = CourseType.AccreditationID
WHERE CourseEnrolment.ContactID = :ContactID
通过使用CreateSQLQuery
在代码中通过nHibernate手动调用SQL来实现此目的是唯一的方法,还是可以使用命名查询之类的方式来表达这种关系?什么是正确的方法?任何指导将不胜感激。
答案 0 :(得分:1)
我看到了几个选项:
您可以使用SqlSelect
,SqlUpdate
等来指定用于选择/更新等的任意SQL语句。(mapping-by-code示例;我确定有一个XML等价物)
您可以将SQL查询映射到QueryOver
查询,并使用它来初始化Accreditation
集合。有点像:
public Contact GetContact(int id)
{
var contact = _session.Get(id);
contact.AccreditationList = _session.QueryOver<Accreditation>() /* your query here */;
return contact;
}
然而!!这种方法有几个缺点 -
GetContact
方法,则无法正确填充您的收藏集。 您可以将中间实体(Course
)映射到您的Contact
实体(如果您不想公开它们,可以将其作为私有成员),然后您的AccreditationList
财产将是
public IEnumerable<Accreditaion> AccreditationList
{
get
{
return _courses.SelectMany(course => course.Accreditations);
}
}
但是,您无法直接操纵Contact
的{{1}}。
最好的解决方案是在映射中使用AccreditationList
选项,但AFAIK没有...
就个人而言,我会选择第三种选择,因为它对我来说似乎是最干净的。