2011-02-07 2 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; } 

는 다음과 같이 더 많은 열이 있습니다 - 그들은 응용 프로그램 설치하여 현재 십 년이 미리 채워져 있습니다. 따라서 전체 테이블의 각 날짜에는이 테이블에 행이 있으며 각 호출에는 발생한 날짜에 대한 링크가 있습니다. 이것은 모두 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() }); 

를 "호출"을 IQueryable이 저장소 인터페이스를 통해 NHibernates LINQ 공급자 (쿼리)에서 반환 된 기본적으로. 위의 쿼리는 저에게 정확한 결과를 제공합니다. NHibernate Profiler는 SQL이 매우 최적이라는 것을 보여 주며 모든 것이 잘됩니다.

그러나 조금 더 진보 된 것을하고 싶다면, 나는 고생한다. 평일 평균 통화 수를 원한다고 가정 해보십시오. 위와 너무 멀지 않은가? 결과 세트에있는 각 요일의 고유 한 날짜 수를 파악하고 총 호출 수를 나누면됩니다. 우리는 모두 설정되어 있습니까? 음, 아니요, 이것이 NHibernate LINQ 공급자의 한계에 부딪히기 시작하는 곳입니다. 개체에 LINQ와 나는 그것을 할 수있는 쿼리를 생성 할 수 -

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

의 라인을 따라 뭔가를 NHibernate에 그것을 사용하는 경우 그러나,이 올바른 쿼리로 변환하지 않습니다. 대신 위의 두 .Count() 호출을 호출 레코드의 수 (*)를 동일하게 설정하므로 결과는 항상 1입니다.

물론 각 호출, 평일 및 날짜를 ​​a로 쿼리해야합니다. 새로운 익명 객체, 그런 다음 응용 프로그램 측면에서 수학을 수행하지만, 일반적인 지혜에 따르면, 그건 그냥 틀렸어 (TM). 나는 절망에서 그것을 끝낼 수 있었다, tho, 심지어 tho는 테이블이 100만의 ++ 전화까지 성장할 때 고통을 의미한다.

다음은 내가 찾고있는 결과를 제공하는 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

+0

글쎄요, 흥미로운 점입니다. 그러나 "사실"테이블의 각 항목 (예 : 내 사례의 호출)은 각 관련 차원 테이블에 하나의 FK가 있음을 이해합니다. 통화 날짜를 파악하고 각 통화 기록에서 해당 통화를 가리키는 데 도움이되는 별표 스키마를 만들려면 어떻게해야합니까? 그러나 일반적으로 나는 잘못된 방향으로 갈 가능성에 대해 매우 열려 있습니다. :) –

답변

1

LINQ 공급자가 할 수없는 일이 많습니다. HQL이나 CreateCriteria를 사용하는 것은 NHibernate에서 받아 들여야 할 것입니다.

나는 그것을 시도하지는 않았지만 HQL이나 CreateCriteria (DetatchedCriteria 포함)를 사용하여 원하는 것을 할 수 있어야한다.

필사적 인 경우 CreateSqlQuery를 사용하여 일반 SQL로 되돌릴 수도 있습니다.

+1

안녕하세요, 귀하의 회신에 감사드립니다. 예,이 문제로 되돌아 가야 할 수도 있습니다. 문제는 기본적으로 사용자에게 IQueryable 을 기반으로 API를 제공하여 그룹화를 위해 IQueryable을 전달하기 전에 Where()로 필터링을 수행 할 수 있도록하려는 것입니다. 그것은 매우 우아했을 것입니다 - 내가 정말로해야할 일은 훌륭한 코더가되어 NHibernate에 기여하는 것입니다. :) 입력 해 주셔서 감사 드리며, HQL 및 ICriteria 방식을 살펴 보겠습니다. –