2010-06-15 63 views
0

我在我的應用程序中有Canine和CanineHandler對象。 CanineHandler對象具有一個PersonID(它引用一個完全不同的數據庫),一個EffectiveDate(它指定一個處理程序何時以canine開始)以及一個對Canine(CanineID)的FK引用。在nhibernate中選擇最新的組

給定一個特定的PersonID,我想找到他們目前負責的所有犬。 (簡化)查詢我會在SQL中使用將是:下面添加映射文件:

Select Canine.* 
    from Canine 
     inner join CanineHandler on(CanineHandler.CanineID=Canine.CanineID) 
     inner join 
      (select CanineID,Max(EffectiveDate) MaxEffectiveDate 
       from caninehandler 
       group by CanineID) as CurrentHandler 
      on(CurrentHandler.CanineID=CanineHandler.CanineID 
       and CurrentHandler.MaxEffectiveDate=CanineHandler.EffectiveDate) 
    where [email protected] 

編輯

<class name="CanineHandler" table="CanineHandler" schema="dbo"> 
    <id name="CanineHandlerID" type="Int32"> 
     <generator class="identity" /> 
    </id> 
    <property name="EffectiveDate" type="DateTime" precision="16" not-null="true" /> 
    <property name="HandlerPersonID" type="Int64" precision="19" not-null="true" /> 
    <many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" access="field.camelcase-underscore" /> 
</class> 

<class name="Canine" table="Canine"> 
    <id name="CanineID" type="Int32"> 
     <generator class="identity" /> 
    </id> 
    <property name="Name" type="String" length="64" not-null="true" /> 
    ... 
    <set name="CanineHandlers" table="CanineHandler" inverse="true" order-by="EffectiveDate desc" cascade="save-update" access="field.camelcase-underscore"> 
     <key column="CanineID" /> 
     <one-to-many class="CanineHandler" /> 
    </set> 
    <property name="IsDeleted" type="Boolean" not-null="true" /> 
</class> 

我還沒試過,但我猜我能做到這在HQL中。我沒有必須在HQL中寫任何東西,所以我最終必須解決這個問題,但是我的問題是,我是否可以使用條件/子查詢對象來執行此子查詢。

我得到儘可能創建以下超脫標準:

DetachedCriteria effectiveHandlers = DetachedCriteria.For<Canine>() 
       .SetProjection(Projections.ProjectionList() 
        .Add(Projections.Max("EffectiveDate"),"MaxEffectiveDate") 
        .Add(Projections.GroupProperty("CanineID"),"handledCanineID") 
       ); 

,但我無法弄清楚如何做內部聯接。如果我這樣做:

Session.CreateCriteria<Canine>() 
    .CreateCriteria("CanineHandler", "handler", NHibernate.SqlCommand.JoinType.InnerJoin) 
    .List<Canine>(); 

我得到一個錯誤「無法解析屬性:CanineHandler的:OPS.CanineApp.Model.Canine」。顯然我錯過了一些東西,但從文檔中我得到的印象是應該返回一個有處理程序的Canine列表(可能帶有重複項)。直到我可以使這項工作,添加子查詢不會工作...

我發現了類似的問題,如Only get latest results using nHibernate,但沒有一個答案真的似乎適用於那種直接的結果我'尋找。

任何幫助或建議,非常感謝。

+1

嗯,這是一個小有點難以在沒有映射的情況下正確回答 - 我通過使用子查詢解決了類似的問題 - 見14.8。 nhibernate參考中的獨立查詢和子查詢 – bernhardrusch 2010-06-16 13:54:01

+0

第一個查詢看起來不太正確 - 它不會獲取當前正在處理的所有狗,而是最近處理的狗。只有當同一天開始處理多隻狗時,纔會返回多個結果。 – mdma 2010-06-18 01:07:06

+0

SQL查詢起作用。它返回一個CanineID列表和最近處理程序分配給狗的日期(即{(1,2010.01.01),(2,2010.03.05),...}。 第二個查詢匹配處理程序記錄我應該提到,在實踐中,EffectiveDate和CanineID唯一標識了CanineHandler中的一行 我沒有在該表上強制執行此替代鍵約束,但即使返回了兩行CanineID和Date對,查詢仍然可以工作 – Kendrick 2010-06-18 17:24:41

回答

1

在上次檢查時,加入到您的示例中的派生表中,CurrentHandler在HQL中不起作用。嘗試映射一個存儲過程,可以讓你編寫任何你喜歡的SQL。下面是一個映射的存儲過程是什麼樣子:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="S2.BP.NHSupport" namespace="S2.BP.Model"> 
    <sql-query name="spGoGetMyDogs" callable="true"> 
    <return-scalar column="PersonID" type="int" /> 
    exec spGoGetMyDogs @PersonID=:personID 
    </sql-query> 
</hibernate-mapping> 

然後,你可以通過你的是PersonID參數,並已NH,象這樣一個變壓器的結果映射回你的對象:

public IEnumerable<Canine> LetTheDogsOut(int personID) { 
    return nhSession.GetNamedQuery("spGoGetMyDogs") 
    .SetInt32("personID", personID) 
    .SetResultTransformer(Transformers.AliasToBean(typeof(Canine))) 
    .List<Canine>(); 
} 
+0

通過Hibernate文檔,我注意到它有一個自然ID的概念,似乎沒有轉移到nHibernate。我試着用HQL來做,並且如你所說,發現似乎不可能。我最終只是在存儲庫中嵌入了一條SQL語句,但可能會按照您的建議切換到SP。感謝您的迴應! – Kendrick 2010-06-23 13:20:21