2010-06-15 13 views
0

У меня есть объекты Canine и CanineHandler в моем приложении. Объект CanineHandler имеет PersonID (который ссылается на совершенно другую базу данных), EffectiveDate (который указывает, когда обработчик запускался с собакой) и ссылку FK на Canine (CanineID).Выберите последнюю группу в 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». Очевидно, что я что-то пропустил, но из документации у меня сложилось впечатление, что должен вернуть список Canines, у которого есть обработчики (возможно, с дубликатами). Пока я не смогу выполнить эту работу, добавление подзапроса не будет работать ...

Я нашел похожие вопросы, такие как Only get latest results using nHibernate, но ни один из ответов действительно не применяется к виду прямого результата I ' м ищет.

Любая помощь или предложение приветствуются.

+1

хорошо, что немного бит жестко отвечать правильно без отображения - я решил подобные проблемы, используя подзапрос - см. 14.8. Отдельные запросы и подзапросы в ссылке nhibernate – bernhardrusch

+0

первый запрос выглядит не совсем корректно - он не будет загружать всех текущих собак, а не собаку, которая была обработана совсем недавно. Множественные результаты будут возвращены только при обработке более одной собаки, начиная с той же даты. – mdma

+0

Работает SQL-запрос. Он возвращает список CanineID и дату, когда последний обработчик был назначен собаке (т. Е. {(1,2010.01.01), (2,2010.03.05), ...}. Второй запрос соответствует записи обработчика по дате и собаке.Я должен упомянуть, что на практике EffectiveDate и CanineID однозначно идентифицируют строку в CanineHandler. Я не ставил альтернативное ограничение ключа в этой таблице, чтобы обеспечить ее выполнение, но даже если бы две строки были возвращены для CanineID & Date, запрос все равно будет работать. – Kendrick

ответ

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, я заметил, что у нее есть концепция естественного идентификатора. Это, похоже, не переместилось на nHibernate.Я попытался сделать это в HQL и нашел, как вы сказали, это казалось невозможным. Я закончил тем, что просто ввел инструкцию SQL в свой репозиторий, но могу переключиться на SP по вашему выбору. Спасибо за ответ! – Kendrick

Смежные вопросы