2011-02-07 89 views
8

我有一個應用程序,它使用一些數據倉庫原理(如維度建模)在相當簡單的數據庫上進行報告。SQL中的統計查詢 - 這可能與NHibernate的LINQ?

一個例子(簡體)實體命名的呼叫看起來是這樣的:

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; } 

有很多更喜歡這個欄目 - 他們預填充通過應用程序安裝在當前十年。因此,整個十年中的每個日期在該表中都有一排,每個Call都有一個到它發生日期的鏈接。這是所有映射在流利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() }); 

在這個例子中,「呼叫」基本上是一個IQueryable通過倉庫接口從NHibernates LINQ提供程序(查詢)返回。上面的查詢給了我正確的結果,NHibernate Profiler告訴我SQL是非常優化的,一切都很好。

但是,如果我想做些稍微更高級的事情,我會陷入困境。假設我希望每週工作日的平均通話次數。離上述不太遠,對吧?我只需要計算出每個工作日在結果集中的唯一日期數量,然後除以它的總呼叫數量,然後我們全部設置 - 對嗎?嗯,不,這是我開始碰到NHibernate LINQ提供商的限制。隨着LINQ到對象我可以構造一個查詢做到這一點 - 沿

.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提供程序執行此操作?或者,如果這是不可能的,那麼我必須讓應用程序獲取中間結果並完成剩下的工作,然後再離開我有多近?

+0

也許你正在走錯方向。如何創建星型模式並預先填充計算的度量? – epitka 2011-02-08 14:02:26

+0

好吧,這是一個有趣的觀點 - 但是,我的理解是,「事實」表中的每個實體(即我的示例中的調用)對每個相關維度表都有一個FK。我如何創建一個星型模式,以幫助我找出呼叫的日期,並從每個呼叫記錄中指出它?但是總的來說,我對這種錯誤的方式進行討論的可能性非常開放。 :) – 2011-02-08 14:43:40

回答

1

有很多事情你不能用LINQ提供程序來做。使用HQL或CreateCriteria只是你必須接受NHibernate的一些東西。

我還沒有嘗試過,但看起來應該可以使用HQL或CreateCriteria(使用DetatchedCriteria)來執行您想要的操作。

如果您絕望,也可以使用CreateSqlQuery回退到純SQL。