2013-01-31 1 views
6

を照会あり、異なるフィールドで何度も同じことをしなければならないは、これら二つのLINQでの重複を減らすためにどのような方法が報告書の束を構築

public List<ReportSummary> ListProducer() 
    { 
     return (from p in Context.stdReports      
       group p by new { p.txt_company, p.int_agencyId } 
        into g 
        select new ReportSummary 
        { 
         PKi = g.Key.int_agencyId, 
         Name = g.Key.txt_company, 
         Sum = g.Sum(foo => foo.lng_premium), 
         Count = g.Count() 
        }).OrderBy(q => q.Name).ToList(); 
    } 

    public List<ReportSummary> ListCarrier() 
    { 
     return (from p in Context.stdReports 
       group p by new { p.txt_carrier, p.int_carrierId } 
        into g 
        select new ReportSummary 
        { 
         PKi = g.Key.int_carrierId, 
         Name = g.Key.txt_carrier, 
         Sum = g.Sum(foo => foo.lng_premium), 
         Count = g.Count() 
        }).OrderBy(q => q.Name).ToList(); 
    } 

私の心がどのように私はかもしれないの空白を描いていますこれら2つを一緒に持って来ることができます。

+0

SQLのようなクエリ表記法の代わりに拡張方法(ドット表記法)を使用すると、グループ化したラムダを除き、両方のクエリが同じように見えます。私はちょうど 'Func keySelector'の変更を推測しています。[IEnumerable.GroupBy](http://msdn.microsoft.com/en-us/library/bb534501(v = vs。 100).aspx)をmsdnに追加します。したがって、あなたは 'Func myKeySelector'を持ち、残りは共通コードです。私が十分な意味を持っているのかどうか、夜遅くまで待っていて、私は新しいOSX上にいるので、今はC#を書くことはできません。 – gideon

+0

式ツリーを使用して動的クエリを構築できます。 –

答えて

0

2つのクエリ間の変更はすべてグループキーであるため、パラメータ化します。それはコンポジットキー(複数の値があります)であるため、これらの値を保持できるシンプルなクラス(汎用名付き)を作成する必要があります。

この場合、パラメータ化するには、キーセレクタを関数のパラメータにします。これを動作させるには、式とメソッドの構文が必要です。あなたは、その関数にそれを一般化できます。

public class GroupKey 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

private IQueryable<ReportSummary> GetReport(
    Expression<Func<stdReport, GroupKey>> groupKeySelector) 
{ 
    return Context.stdReports 
     .GroupBy(groupKeySelector) 
     .Select(g => new ReportSummary 
     { 
      PKi = g.Key.Id, 
      Name = g.Key.Name, 
      Sum = g.Sum(report => report.lng_premium), 
      Count = g.Count(), 
     }) 
     .OrderBy(summary => summary.Name); 
} 

それからちょうど適切なキーセレクタを使用して、クエリでこの機能を使用しています。

public List<ReportSummary> ListProducer() 
{ 
    return GetReport(r => 
     new GroupKey 
     { 
      Id = r.int_agencyId, 
      Name = r.txt_company, 
     }) 
     .ToList(); 
} 

public List<ReportSummary> ListCarrier() 
{ 
    return GetReport(r => 
     new GroupKey 
     { 
      Id = r.int_carrierId, 
      Name = r.txt_carrier, 
     }) 
     .ToList(); 
} 

あなたのエンティティにどのようなタイプのマッピングをしているかわからないので、私はいくつか前提をしました。あなたの場合に適切なものを使用してください。

1

グループパラメータの変更が唯一のように見えます。グループ化パラメータを指定するラムダを受け入れるラッパー関数を記述できますか?または、LINQを使用する代わりに、2つの文字列を受け取り、生のT-SQLを構築するラッパー関数ですか?

これがコンパイルされるかどうかわからない場合は、groupステートメントのフィールドの別名を付けて、同じ方法でグループ化構文を常に参照できます(g.Key.id1g.Key.id2など)。その後、グループ化コンストラクトをReportSummaryコンストラクタに渡して、左/右の代入を1か所で行います。あなたはこのような何か行うことができます

+0

「選択」の匿名タイプも異なります。 –

+0

グループ化オブジェクトを参照する方法のみ。オブジェクトの構造はどちらの場合も同じですので、一般化することができると思います(それはthemme86の回答のようなものです) –

1

(あなたは、コールサイトでその匿名オブジェクト以来、しかしダイナミックとしてそれを渡す必要があるだろう):

public List<ReportSummary> GetList(Func<Record, Tuple<string, int>> fieldSelector) 
{ 
    return (from p in Context.stdReports      
     group p by fieldSelector(p) 
      into g 
      select new ReportSummary 
      { 
       PKi = g.Key.Item2 
       Name = g.Key.Item1, 
       Sum = g.Sum(foo => foo.lng_premium), 
       Count = g.Count() 
      }).OrderBy(q => q.Name).ToList(); 
} 

をそして、あなたはこのようにそれを呼び出すことができます。

var summary = GetList(rec => Tuple.Create(rec.txt_company, rec.int_agencyId)); 

か:もちろん

var summary = GetList(rec => Tuple.Create(rec.txt_carrier, rec.int_carrierId)); 

、あなたはwhateでRecordを交換したいと思いますverタイプContext.stdReportsが実際に復帰しています。

私はそれがコンパイルされるかどうかは確認していませんが、あなたはそのアイディアを得ています。

+2

これはクエリプロバイダであり、オブジェクトへのLINQではなく、式 'Func >' IQueryable'オーバーロードを使用できるようにする実際の関数ではなく、 – Servy

関連する問題