12

ゼロ以外の残高の注文を返す linq to sql クエリがあります (実際、クエリは少し複雑ですが、簡単にするために一部の詳細を省略しました)。このクエリは、CardItems を含まない注文も返す必要があります (両方のサブクエリが T-SQL で NULL を返し、2 つの NULLS を比較すると FALSE になるため、比較のためにサブクエリの NULL 結果値を 0 に変換します)。

var q = (from o in db.Orders
         where db.Cards(p =>
             p.OrderId == o.Id 
             && p.Sum + (db.CardItems.Where(i => i.IncomeId == p.Id)
                        .Sum(i => (double?)i.Amount) ?? 0) 
                    != (db.CardItems.Where(i => i.DeductId == p.Id)
                        .Sum(i => (double?)i.Amount) ?? 0)
            ).Any()
         select o);

問題は、変換式 Sum(i => (double?)i.Amount) ?? 0は COALESCE 演算子を生成します。これは、サブクエリのために COALESCE をISNULLに置き換えたまったく同じ T-SQL クエリよりも 10 倍遅くなります。この状況で ISNULL を生成する可能性はありますか?

4

2 に答える 2

2

私の経験では、必要な SQL を生成するように linq を誘導することは、せいぜい面倒です。linq よりも優れた (正しく動作し、適切に実行される) クエリの実装がある場合は、この 1 つのクエリだけであっても、それを使用してください。

最も速い方法は、おそらく を使用することDataContext.ExecuteQuery<TResult>です。linq がクエリ自体を生成したかのように、返されたオブジェクトをハイドレートして処理します。

http://msdn.microsoft.com/en-us/library/bb361109.aspx

多くの人は、この SQL をストアド プロシージャ、特にプロダクション コードに配置したいと考えています。次に、ストアド プロシージャを linq オブジェクトにマップするだけで、同じように機能します。よくあることですが、ScottGu はその方法についてかなり詳細な投稿をしています。

http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrifying-data-using-stored-procedures.aspx

于 2012-07-13T07:40:22.363 に答える
0

Amount のない行はゼロとして合計されると想定しているため、Amount のない行を除外するだけで、IsNull や合体について心配する必要はありません。

&& p.Sum + (db.CardItems.Where(i => i.IncomeId == p.Id)
                    .Where(i=> i.Amount > 0)
                    .Sum(i => (double?)i.Amount) ?? 0) 
                != (db.CardItems.Where(i => i.DeductId == p.Id)
                    .Where(i=> i.Amount > 0)
                    .Sum(i => (double?)i.Amount) ?? 0)

私はあなたのオブジェクトを知らないので、キャスト (ダブル?) とデフォルト (??) 演算子を削除することさえできるかもしれません

于 2012-06-08T15:23:34.227 に答える