1

我在我的最新项目中使用了 nHibernate,并成功映射了所有基本关系,其中值存在于我正在使用的主表中或通过像复合这样的简单关系。

我遇到困难的地方是如何映射复杂的连接?

例如,我有一个名为Contacteach的实体contact,它具有您常用的属性,例如 Name、DOB、Phone.... 但我还需要它有一个名为的属性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

是通过 nHibernate 在代码中手动调用 SQL 来完成此操作的唯一方法,CreateSQLQuery或者我可以使用命名查询之类的东西来表达这种关系吗?什么是正确的方法?任何指导将不胜感激。

4

1 回答 1

1

我看到了几个选项:

  1. 您可以使用SqlSelect, SqlUpdateetc.. 来指定用于选择/更新等的任意 SQL 语句。(按代码映射示例;我确定有一个 XML 等效项)

  2. 您可以将您的 SQL 查询映射到一个QueryOver查询,并使用它来初始化您的Accreditation集合。类似于以下内容:

    public Contact GetContact(int id) { var contact = _session.Get(id); contact.AccreditationList = _session.QueryOver<Accreditation>() /* your query here */; return contact; }
    然而!!这种方法有几个缺点——

    • 如果您不使用该GetContact方法,您的集合将无法正确填充。
    • 它不支持查询联系人很容易(首先您必须查询联系人,然后您必须初始化每个联系人的认证列表)。
  3. 您可以将中间实体 ( Course) 映射到您的Contact实体(如果您不想公开它们,您可以将其作为私有成员),然后您的AccreditationList财产将是

public IEnumerable<Accreditaion> AccreditationList { get { return _courses.SelectMany(course => course.Accreditations); } } 但是,您将无法直接操作Contact's AccreditationList

最好的解决方案是QueryOverSelect在映射中有类似的选项,但 AFAIK 没有......
我个人会选择第 3 个选项,因为它对我来说似乎是最干净的。

于 2012-09-25T09:37:22.233 回答