SQL中的统计查询 - NHibernate LINQ可以实现吗?

时间:2011-02-07 22:01:18

标签: sql linq nhibernate linq-to-nhibernate

我有一个应用程序,它使用一些数据仓库原则(如维度建模)来对相当简单的数据库进行报告。

名为Call的示例(简化)实体如下所示:

    public virtual long Id { get; set; }
    public virtual string OriginatorNumber { get; set; }
    public virtual string DestinationNumber { get; set; }
    public virtual DateDimension DateDimension { get; set; }

真实模型的一些属性已被删除,因为它们无关紧要。简化的DateDimension如下所示:

    public virtual long Id { get; set; }
    public virtual DateTime Date { get; set; }
    public virtual int DayOfMonth { get; set; }
    public virtual int Weekday { get; set; }

还有很多这样的专栏 - 它们通过应用程序设置预先填充了当前十年。因此,整个十年中的每个日期在此表中都有一行,每个调用都有一个指向它发生日期的链接。这全部映射在Fluent NHibernate中并且工作正常。

如果我想做一些报告,我可以使用3.0中改进的NHibernate LINQ提供程序轻松完成。我们希望使用LINQ来提高我们提供的可维护性,但如果我们真的必须,我们将考虑HQL,ICriteria甚至纯SQL。

所以说我想建立一个报告,显示来自某个数字的呼叫数量除以它们出现的星期几。我可以这样轻松地做到这一点:

        var query = Calls
            .Where(c => c.OriginatorNumber == "402")
            .GroupBy(c => c.DateDimension.Weekday)
            .Select(g => new { Day = g.Key, Calls = g.Count() } );

在此示例中,“Calls”基本上是通过存储库接口从NHibernates LINQ提供程序(Query)返回的IQueryable。上面的查询给出了正确的结果,NHibernate Profiler向我展示了SQL非常优秀,一切都很好。

然而,如果我想做一些更先进的事情,我会陷入困境。假设我想要每个工作日的平均呼叫次数。离上面不太远吧?我只需要弄清楚每个工作日在结果集中的唯一日期数,除以它的总呼叫次数,我们都设置好了 - 对吗?嗯,不,这是我开始遇到NHibernate LINQ提供程序的限制的地方。使用LINQ to对象,我可以构造一个查询来执行它 - 就像

那样
.Select(g => g.Count() / g.GroupBy(c => c.DateDimension.Date).Count());

但是,在NHibernate中使用它时,这不会转换为正确的查询。相反,它将上面的.Count()调用转换为相同的调用记录数(*),因此结果始终为1.

我当然可以将每个调用,工作日和日期作为一个新的匿名对象进行查询,然后在应用程序方面进行数学运算,但根据传统观点,那是错误的(t​​m)。我最终可能会绝望地做到这一点,甚至,当桌子变成一百万个++电话时,这意味着痛苦。

以下是一个SQL查询,它为我提供了我正在寻找的结果。

select ss.Weekday, AVG(cast(ss.Count as decimal))
from
(
select dd.Weekday, dd.Date, COUNT(*) as Count
from Call c
left outer join DateDimension dd
    on c.DateDimension_id = dd.Id
where c.OriginatorNumber = '402'
group by dd.Weekday, dd.Date
) ss
group by ss.Weekday
order by ss.Weekday

是否可以使用NHibernate LINQ提供程序执行此操作?或者,如果那是不可能的,在我必须让应用程序获取中间结果并完成剩下的工作之前,我能有多接近?

1 个答案:

答案 0 :(得分:1)

LINQ提供程序有很多事情你无法做到。使用HQL或CreateCriteria只是NHibernate必须接受的东西。

我还没有尝试过,但看起来你应该能够使用HQL或CreateCriteria(使用DetatchedCriteria)做你想做的事。

如果你绝望,你也可以使用CreateSqlQuery回退到纯SQL。