将HQL查询转换为Criteria会生成无效的SQL

时间:2009-11-10 00:50:52

标签: nhibernate

我正在尝试将以下HQL查询转换为Criteria。

from SubportfolioAudit as a
where a.ID in (select max(a2.ID)
                from SubportfolioAudit as a2
                where a2.EffectiveDate = :EffectiveDate
                    and a.Subportfolio.ID = a2.Subportfolio.ID
                group by a2.Subportfolio.ID)
and a.Subportfolio.ID in (:SubportfolioList)

到目前为止,我有以下内容:

var crit =  Session.CreateCriteria(typeof(SubportfolioAudit));
var currentAuditByEffectiveDate = DetachedCriteria.For(typeof(SubportfolioAudit))
                                  .SetProjection(Projections.ProjectionList()
                                                    .Add(Projections.Max("ID"))
                                                    .Add(Projections.GroupProperty("Subportfolio.ID")))
                                  .Add(Expression.Eq("EffectiveDate", effectiveDate));

crit.Add(Subqueries.PropertyIn("ID", currentAuditByEffectiveDate));
crit.Add(Expression.In("Subportfolio.ID", subportfolioList.Select(x => x.ID).ToArray()));

return crit.List<SubportfolioAudit>();

生成无效的子查询,您可以在此处看到:

SELECT this_.SubportfolioAuditId        as Subportf1_21_6_,
       this_.Event                      as Event21_6_,
       this_.CreatedDate                as CreatedD3_21_6_,
       this_.[User]                     as User4_21_6_,
       this_.EffectiveDate              as Effectiv5_21_6_,
       this_.SubportfolioId             as Subportf6_21_6_,
       subportfol2_.SubportfolioId      as Subportf1_12_0_,
       subportfol2_.PACERCode           as PACERCode12_0_,
       subportfol2_.HedgeRatio          as HedgeRatio12_0_,
       subportfol2_.Name                as Name12_0_,
       subportfol2_.Strategy            as Strategy12_0_,
       subportfol2_.BasketId            as BasketId12_0_,
       subportfol2_.PortfolioId         as Portfoli7_12_0_,
       subportfol2_.ReferenceBasketId   as Referenc8_12_0_,
       (SELECT CASE 
                 WHEN Count(* ) > 0
                 THEN 1
                 ELSE 0
               END
        FROM   Asset
        WHERE  Asset.SubportfolioId = subportfol2_.SubportfolioId) as formula1_0_,
       basket3_.BasketId                as BasketId7_1_,
       basket3_.Name                    as Name7_1_,
       basket3_.CatsBenchmarkCode       as CatsBenc4_7_1_,
       basket3_.Description             as Descript5_7_1_,
       basket3_.BaseBasketId            as BaseBask6_7_1_,
       basket3_.Filename                as Filename7_1_,
       basket3_.Type                    as Type7_1_,
       basket4_.BasketId                as BasketId7_2_,
       basket4_.Name                    as Name7_2_,
       basket4_.CatsBenchmarkCode       as CatsBenc4_7_2_,
       basket4_.Description             as Descript5_7_2_,
       basket4_.BaseBasketId            as BaseBask6_7_2_,
       basket4_.Filename                as Filename7_2_,
       basket4_.Type                    as Type7_2_,
       portfolio5_.PortfolioId          as Portfoli1_5_3_,
       portfolio5_.BaseCurrencyCode     as BaseCurr2_5_3_,
       portfolio5_.TradingAccountNumber as TradingA3_5_3_,
       portfolio5_.Name                 as Name5_3_,
       portfolio5_.ClientId             as ClientId5_3_,
       client6_.ClientId                as ClientId4_4_,
       client6_.ExplicitFee             as Explicit2_4_4_,
       client6_.Affiliated              as Affiliated4_4_,
       client6_.ClientGroup             as ClientGr4_4_4_,
       client6_.RCODA                   as RCODA4_4_,
       client6_.Name                    as Name4_4_,
       client6_.BaseCurrencyCode        as BaseCurr7_4_4_,
       client6_.Region                  as Region4_4_,
       basket7_.BasketId                as BasketId7_5_,
       basket7_.Name                    as Name7_5_,
       basket7_.CatsBenchmarkCode       as CatsBenc4_7_5_,
       basket7_.Description             as Descript5_7_5_,
       basket7_.BaseBasketId            as BaseBask6_7_5_,
       basket7_.Filename                as Filename7_5_,
       basket7_.Type                    as Type7_5_
FROM   dbo.SubportfolioAudit this_
       inner join dbo.Subportfolio subportfol2_
         on this_.SubportfolioId = subportfol2_.SubportfolioId
       left outer join dbo.Basket basket3_
         on subportfol2_.BasketId = basket3_.BasketId
       left outer join dbo.Basket basket4_
         on basket3_.BaseBasketId = basket4_.BasketId
       left outer join dbo.Portfolio portfolio5_
         on subportfol2_.PortfolioId = portfolio5_.PortfolioId
       left outer join dbo.Client client6_
         on portfolio5_.ClientId = client6_.ClientId
       left outer join dbo.Basket basket7_
         on subportfol2_.ReferenceBasketId = basket7_.BasketId
WHERE  this_.SubportfolioAuditId in (SELECT   max(this_0_.SubportfolioAuditId) as y0_,
                                              this_0_.SubportfolioId           as y1_
                                     FROM     dbo.SubportfolioAudit this_0_
                                     WHERE    this_0_.EffectiveDate = '2009-09-11T00:00:00.00' /* @p0 */
                                     GROUP BY this_0_.SubportfolioId)
       and this_.SubportfolioId in (13 /* @p1 */,14 /* @p2 */,15 /* @p3 */,16 /* @p4 */,
                                    17 /* @p5 */,18 /* @p6 */,19 /* @p7 */,20 /* @p8 */,
                                    21 /* @p9 */)

我知道Projections.GroupProperty()导致了这个问题,但我似乎无法找到另一种方法来实现我想要的目标。

1 个答案:

答案 0 :(得分:1)

我相信(并纠正我,如果我错了)子查询无效,因为你缺少你在HQL中设置的第二个where子句(...和a.Subportfolio.ID = a2.Subportfolio.ID )。

如下所示转换您的Criteria查询我相信(无法验证,因为我无法测试您的代码)它会做到这一点。

var crit = Session.CreateCriteria(typeof(SubportfolioAudit), "mainQuery");
var currentAuditByEffectiveDate = DetachedCriteria.For(typeof(SubportfolioAudit),"subQuery")
              .SetProjection(Projections.ProjectionList()
                                .Add(Projections.Max("ID"))
                                .Add(Projections.GroupProperty("Subportfolio.ID")))
              .Add(Expression.Eq("EffectiveDate", effectiveDate));
              .Add(Expression.EqProperty("subQuery.ID", "mainQuery.ID"));

crit.Add(Subqueries.PropertyIn("mainQuery.ID", currentAuditByEffectiveDate));
crit.Add(Expression.In("mainQuery.Subportfolio.ID", subportfolioList.Select(x => x.ID).ToArray()));

return crit.List<SubportfolioAudit>();

我所做的是在DetachedCriteria中添加一个额外的where子句,该子句将子查询的SubportfoliAudit.ID列与外部主查询“连接”起来。我还提供了别名来命名查询。