如何使用Hibernate Criteria进行分组,获取关联和T-SQL函数

时间:2010-03-05 12:00:28

标签: tsql nhibernate group-by icriteria

我想创建以下T-SQL语句:

SELECT  SUM (sa.Amount) as 'SumAmount',
        SUM(sa.Cost) as 'SumCost', 
        gg.[Description] as 'Goodsgroup', Month(sa.[Date]) as 'Month' 
FROM SalesmanArticle sa
INNER JOIN Article a
    ON a.ArticleId = sa.ArticleId
INNER JOIN GoodsGroup gg
    ON gg.GoodsGroupId = a.GoodsGroupId
GROUP BY gg.[Description], Month(sa.[Date])
ORDER BY 'Month', 'Goodsgroup'

这可能与NHibernates ICriteria有关吗?

如何使用Month-T-SQL函数?

我是否必须手动加入,或者ICriteria API是否知道当我使用propetyName'SalesmanArticle.Article.Goodsgroup.Description'时,它必须加入文章和商品组?

编辑:

现在我在这里写了这段代码:

// typesafe properties
string article = typeof(Article).Name;
string goodsGroup = typeof(GoodsGroup).Name;
string salesmanArticle = typeof(SalesmanArticle).Name;

string amount = Reflector.GetPropertyName<SalesmanArticle>(x => x.Amount);
string cost = Reflector.GetPropertyName<SalesmanArticle>(x => x.Cost);
string description = string.Format("{0}.{1}",
    goodsGroup, Reflector.GetPropertyName<SalesmanArticle>(x => x.Article.GoodsGroup.Description));
string date = Reflector.GetPropertyName<SalesmanArticle>(x => x.Date);

string formatedDate = string.Format("MONTH([{0}])", date);

return GetSession()
    // FROM
    .CreateCriteria(typeof(SalesmanArticle), salesmanArticle)
    // JOIN
        .CreateCriteria(article, article, JoinType.InnerJoin)
        .CreateCriteria(goodsGroup, goodsGroup, JoinType.InnerJoin)
    // SELECT
        .SetProjection(Projections.ProjectionList()
                           .Add(Projections.Sum(amount))
                           .Add(Projections.Sum(cost))
    // GROUP BY
                           .Add(Projections.GroupProperty(description))
                           .Add(Projections.SqlGroupProjection(formatedDate, formatedDate, new[]{"MyDate"} , new[] { NHibernateUtil.Int32 })))
        .List();

但抛出了AdoException:

  

无法执行查询[SELECT   sum(this_.Amount)为y0_,   sum(this_.Cost)为y1_,   goodsgroup2_。描述为y2_,   每月([日期])来自[SalesmanArticle]   this_ inner join [文章] article1_   on this_.ArticleId = article1_.ArticleId   内连接[GoodsGroup] goodsgroup2_   上   article1_.GoodsGroupId = goodsgroup2_.GoodsGroupId   GROUP BY goodsgroup2_.Description,   月([日期])]

     

[SQL:SELECT   sum(this_.Amount)为y0_,   sum(this_.Cost)为y1_,   goodsgroup2_。描述为y2_,   每月([日期])来自[SalesmanArticle]   this_ inner join [文章] article1_   on this_.ArticleId = article1_.ArticleId   内连接[GoodsGroup] goodsgroup2_   上   article1_.GoodsGroupId = goodsgroup2_.GoodsGroupId   GROUP BY goodsgroup2_.Description,   个月([日期])]

奇怪的是NHibernate试图创建2个查询?!

他们两个都是正确的!

而不是代码行

.Add(Projections.SqlGroupProjection(formatedDate, formatedDate, new[]{"MyDate"} , new[] { NHibernateUtil.Int32 })))

我用过

.Add(Projections.SqlFunction("MONTH", NHibernateUtil.Int32, Projections.GroupProperty(date))))

SqlFunction的问题在于它创建了GROUP BY sa.Date而不是MONTH(sa.Date)。但这种方法在语法上是正确的。

所以我切换到了SqlGroupProjection方法。

但无论如何它不起作用。

有人能帮助我吗?

1 个答案:

答案 0 :(得分:6)

我解决了。这是正确的代码:

public class SalesmanArticleRepository : Repository<SalesmanArticle>, ISalesmanArticleRepository
{
    public IList GetAllAll()
    {
        // typesafe properties
        string article = typeof(Article).Name;
        string goodsGroup = typeof(GoodsGroup).Name;
        string salesmanArticle = typeof(SalesmanArticle).Name;

        string amount = Reflector.GetPropertyName<SalesmanArticle>(x => x.Amount);
        string cost = Reflector.GetPropertyName<SalesmanArticle>(x => x.Cost);
        string description = string.Format("{0}.{1}",
            goodsGroup, Reflector.GetPropertyName<SalesmanArticle>(x => x.Article.GoodsGroup.Description));
        string date = Reflector.GetPropertyName<SalesmanArticle>(x => x.Date);

        string formatedDateSql = string.Format("month({{alias}}.[{0}]) as mydate", date);
        string formatedDateGroupBy = string.Format("month({{alias}}.[{0}])", date);

        return GetSession()
            // FROM
            .CreateCriteria(typeof(SalesmanArticle), salesmanArticle)
            // JOIN
                .CreateCriteria(article, article, JoinType.InnerJoin)
                .CreateCriteria(goodsGroup, goodsGroup, JoinType.InnerJoin)
            // SELECT
                .SetProjection(Projections.ProjectionList()
                                   .Add(Projections.Sum(amount))
                                   .Add(Projections.Sum(cost))
            // GROUP BY
                                   .Add(Projections.GroupProperty(description))
                                   .Add(Projections.SqlGroupProjection(formatedDateSql, formatedDateGroupBy, new[] { "mydate" }, new[] { NHibernateUtil.Int32 })))
                .List();
    }
}