【问题标题】:Select latest group by in nhibernate在 nhibernate 中选择最新的分组依据
【发布时间】:2010-06-15 18:34:41
【问题描述】:

我的应用程序中有 Canine 和 CanineHandler 对象。 CanineHandler 对象有一个 PersonID(它引用一个完全不同的数据库)、一个 EffectiveDate(它指定处理程序何时从该犬开始)和一个对犬 (CanineID) 的 FK 引用。

给定一个特定的 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 CanineHandler.HandlerPersonID=@PersonID

编辑:在下面添加了映射文件:

<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 of:OPS.CanineApp.Model.Canine”。显然我遗漏了一些东西,但从文档中我得到的印象是应该返回一个具有处理程序的犬类列表(可能有重复项)。在我能完成这项工作之前,添加子查询是行不通的......

我发现了类似的问题,例如 Only get latest results using nHibernate,但似乎没有一个答案真正适用于我正在寻找的那种直接结果。

非常感谢任何帮助或建议。

【问题讨论】:

  • 好吧,如果没有映射,这有点难以正确回答 - 我已经通过使用子查询解决了类似的问题 - 请参阅 14.8。 nhibernate 引用中的分离查询和子查询
  • 第一个查询看起来不太正确 - 它不会获取所有当前正在处理的狗,而是获取最近处理的狗。仅当从同一日期开始处理多只狗时,才会返回多个结果。
  • SQL 查询有效。它返回 CanineID 列表和最新处理程序分配给狗的日期(即 {(1,2010.01.01),(2,2010.03.05),...}。第二个查询按日期匹配处理程序记录和狗。我应该提一下,在实践中,EffectiveDate 和 CanineID 唯一标识 CanineHandler 中的一行。我没有在该表上放置备用键约束来强制执行此操作,但即使为 CanineID 和日期对返回了两行,查询仍然有效。

标签: c# nhibernate


【解决方案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>();
}

【讨论】:

  • 翻阅Hibernate文档,我注意到它有一个自然ID的概念。这似乎并没有转移到 nHibernate。我尝试在 HQL 中执行此操作,发现如您所说,这似乎是不可能的。我最终只是在我的存储库中嵌入了一条 SQL 语句,但可能会按照您的建议切换到 SP。感谢您的回复!
猜你喜欢
  • 1970-01-01
  • 2013-03-15
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 2017-10-18
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多