2
public class DailyAggregator : Aggregator 
{ 
    public override Dictionary<string, int?> Aggregate<T>(IQueryable<T> query, Expression<Func<T, DateTime>> groupByProperty, Expression<Func<T, double>> operationProperty = null) 
    { 
     if (operationProperty == null) // property of sum/avg (null = count) 
      operationProperty = x => 1; 

     if (_operationType.Equals(ReportAggregationOperation.Sum)) 
     { 
      return query 
       .GroupBy(g => new 
       { 
        Day = TestableDbFunctions.TruncateTime(groupByProperty.Invoke(g)) 
       }) 
       .Select(x => new 
       { 
        Key = x.Key.Day.ToString().Substring(0, 10), 
        Value = (int?) x.Sum(operationProperty.Compile()), 
       }) 
       .ToDictionary(t => t.Key, t => t.Value); 
     } 
     else 
     { 
      return query 
       .GroupBy(g => new 
       { 
        Day = DbFunctions.TruncateTime(groupByProperty.Invoke(g)) 
       }) 
       .Select(
       x => new 
       { 
        Key = x.Key.Day.ToString().Substring(0, 10), 
        Value = (int?) x.Average(operationProperty.Compile()), 
       }).ToDictionary(t => t.Key, t => t.Value); 
     } 
    } 
} 

私はdailyaggreagtor/monthlyaggregator ... のようにインスタンスを作成するためのIOCコンテナを使用しています。しかし、私は表現することで、このグループを構築するために、またはステートメント場合は、上記を排除する権利デザインパターンを適用することができませんでした。if文(SUM/AVG)を使用せずに以下のクエリを実装するにはどうすればよいですか?

コンパイル関数と呼び出し関数は、LinqKit拡張から提供されます。 このアグリゲータを使用するクラスは、DBにクエリを行い、コールセンターレポート(TotalCdrRecordsレポート、ReachedCdrRecordsレポート、CdrTalkTimeレポート、CdrCallAfterworkTimeなど)のデータを収集しています.CDRはコールデータレコードであり、 )。クエリー(T)のタイプはレポートクラスで指定されていますが、基本的にはIReportableEntityですが、もちろんoperationPropertyはcount/sum/avgオペレーションを実行できるDBエンティティの任意のプロパティです。groupByPropertyは常にDateTime列。

これは、次のSQLクエリを生成します。

SELECT 
1 AS [C1], 
SUBSTRING(CASE WHEN ([GroupBy1].[K1] IS NULL) THEN N'' ELSE CAST([GroupBy1].[K1] AS nvarchar(max)) END, 0 + 1, 10) AS [C2], 
CAST([GroupBy1].[A1] AS int) AS [C3] 
FROM (SELECT 
    [Filter1].[K1] AS [K1], 
    SUM([Filter1].[A1]) AS [A1] 
    FROM (SELECT 
     convert (datetime2, convert(varchar(255), [Extent1].[CreatedOn], 102) , 102) AS [K1], 
     cast(1 as float(53)) AS [A1] 
     FROM [dbo].[VCCCdr] AS [Extent1] 
     WHERE ([Extent1].[CreatedOn] >= @p__linq__0) AND ([Extent1].[CreatedOn] <= @p__linq__1) AND ([Extent1].[CompanyId] = @p__linq__2) 
    ) AS [Filter1] 
    GROUP BY [K1] 
) AS [GroupBy1] 
+1

、それが書かれているすべての方法で動作しますか?しかし、建設的には、 'query'、' groupBy'、 'operationProperty'変数のタイプ、' Invoke'と 'Compile'(LINQKit?)の使用など、意味のある答えを得るために欠けている情報があまりにも多いです。 –

+0

はいそれはtostring部分を除いて働いていますが、私は投稿を編集しました。そして、はい、コンパイルと呼び出しは、LinqKitの一部です。 –

答えて

3

あなたがLINQKitを使用しているので、あなたはそれがクエリ内の一部及びInvokeSum/Averageを呼び出すための式を抽出することができます。例えば

:好奇心から

var aggregateFunc = _operationType.Equals(ReportAggregationOperation.Sum) ? 
     Linq.Expr((IEnumerable<double> source) => source.Sum()) : 
     Linq.Expr((IEnumerable<double> source) => source.Average()); 

return query 
    .GroupBy(g => new 
    { 
     Day = DbFunctions.TruncateTime(groupByProperty.Invoke(g)) 
    }) 
    .Select(x => new 
    { 
     Key = x.Key.Day.ToString().Substring(0, 10), 
     Value = (int?)aggregateFunc.Invoke(x.Select(operationProperty.Compile())), 
    }) 
    .ToDictionary(t => t.Key, t => t.Value); 
+0

作品は魅力的です:)ありがとう!私は、これが他の人にとって有用であることを願っています。なぜなら、私は式 –

関連する問題