2012-09-25 43 views
1

我在我最近的項目中使用了nHibernate,併成功映射了所有基本關係,其中值存在於我正在使用的主表中,或者通過像複合這樣的簡單關係存在。映射nHibernate中的複雜連接

我陷入困境的地方在於如何去映射覆雜的連接?

比如我有一個名爲實體Contact每個contact有你平時的屬性,如姓名,出生日期,電話....但我也需要它有一個叫做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或者我可以表達使用類似命名查詢這種關係來實現這一目標的唯一途徑?什麼是正確的方法?任何指導將不勝感激。

回答

1

我看到一對夫婦的選擇:

  1. 您可以使用SqlSelectSqlUpdate等指定任意的SQL語句選擇/更新等。(一mapping-by-code例子,我敢肯定有一個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); } } 您將無法操縱ContactAccreditationList直接,雖然。

最好的解決辦法是有一些像在映射QueryOverSelect選項,但據我所知沒有...
個人而言,我會用第三選項去,因爲它似乎最乾淨的給我。