2009-04-20 1 views
7

冗長性を持つlinqクエリがあります。単一のコードを除外したいと思います。これらはIQueryableである結合式であり、重要なのは、リファクタリングなしでクエリを評価するより早く評価されるということではありません。ここでLINQのリファクタリングIQueryable式を使用してクエリの重複部分を削除する

は単純化されたクエリです:

var result = 
from T in db.Transactions 
join O in db.Orders on T.OrderID equals O.OrderID 
join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails 
let FirstProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName) 
select new 
{ 
    TransactionID = T.TransactionID, 
    OrderID = O.OrderID, 
    FirstProductBought = FirstProductBought 
}; 

私は何をくくり出すしたいことは番目の論理である「ため与えられ、最初の製品は何買っています」。私は他のクエリで同じロジックを使用しています。どうやってそれを共有メソッドに分解できますか?

一般に、コードの再利用とIQueryablesのために、私ができることは、IQueryableを取り込み、出力としてIQueryable/IOrderedQueryableを生成するコードです。このような関数を使用すると、クエリが完全に構築されるまでクエリを延期する再利用可能なコードでLINQ式を構築できます。ここでは、私はint(orderID)しか持っていないので、それを動作させる方法がわかりません。

おかげ

+0

これはLinq'ersにとって非常に高いレベルの質問です。私は同じ基本的なことを尋ね、多くのフィードバックを得ていない。 – Merritt

答えて

4

申し訳ありませんが自分の質問に答えるために、私は良い解決策を見つけました。私は、あなたがやろうとしていることに応じて、IQueryableを評価せずに異なるLINQ式を取り除く方法があります。だから私は人々が代替のソリューションを共有することを望む。

私のソリューションは、分解されたクエリの「ビュー」を作成することでした。私はそれをLINQクライアントの視点から見たSQLビューとよく似ているので、ビューと呼んでいます。ただし、SQLビューとは異なり、索引付けすることも、列を永続化することもできません。したがって、このビューを使用するとボトルネックになるので、実際のSQLビューを使用することが適切です。これにより

static public class MyDataContextExtension 
{ 
    // The view exposes OrderSummary objects 
    public class OrderSummary 
    { 
     public OrderID { get; set; } 
     public string FirstProductListed { get; set; } 
    } 

    static public IQueryable<OrderSummary> OrderySummaryView(this MyDataContext db) 
    { 
     return (
       from O in db.Orders 
       join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails 
       let AProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName) 
       let TotalCost = OrderDetails.Aggregate(0 
       select new OrderSummary() 
       { 
        OrderID = OD.OrderID, 
        FirstProductListed = AProductBought.FirstOrDefault() 
       }; 
    } 
} 

、私は次のように元のクエリを置き換え、クエリの重複部分を考慮することができます:あなたが他の列が追加されて想像することができる

var result = 
from T in db.Transactions 
join OS in db.OrderSummaryView() on T.OrderID equals OS.OrderID 
select new 
{ 
    TransactionID = T.TransactionID, 
    OrderID = T.OrderID, 
    FirstProductBought = OS.FirstProductListed 
}; 

...私は1つのクールなと思います実際には、余分な列を追加しても最終的な選択でそれらを使用しないと、LINQはデータベースからそれらのものを実際に照会しません。

1

同じ問題がありました。これはボックスからはサポートされておらず、LOBアプリケーションの主要な問題です。 LINQ式の再利用に関するコードプロジェクトの記事を書きました。これには、(匿名型を含む)投影の再利用を可能にするLinqExpressionPrjectionという非常に小さなユーティリティが含まれます。

記事hereを検索してください。

投影再利用のアセンブリをnuget packageとし、ソースをCodePlexとすることができます。

投稿から数時間が経過しています。私はまだあなたのために役立つことを願っています。そうでない場合、多分このスレッドを読んでいる他の人に。

+0

ありがとう! http://www.codeproject.com/Articles/402594/Black-Art-LINQ-expressions-reuseにリンクすることを意味しましたか?私にとっては、あなたがあなたの記事のリストに荷物を与えた記事のリンク。 –

0

LINQ式を考慮するもう一つの重要な方法は、例えば、周りの表現を渡すことです:

X GetSomeX(Expression<Func<Y, X>> map) 
{ 
    return SourceOfYs.Select(map); 
} 

私はバラクの記事の記事を調べてアイデアを得た - そして彼は、もう少しその上ないにもかかわらず、トピック、私はここで再びこの作品に言及すると思った。直接的に指摘するのは明らかに最初のことです。

関連する問題