Linq関連の記事のメモ
LinqをORMとして見た時の最適化(カスタマイズ)ってできるのか興味があるので少しLinqの実装を調査し始めました。
Linqも最近はいろいろ情報がでてきてなんとなくイメージがわかるのですがまだまだクリアになっていません。特にクエリ式(Query Expression)の実装部分がSQL文生成に大きく絡んでいるようなのですが、その部分の構造をもう少し理解する必要がありそうです。
とりあえず、リンクをメモっておきます。
Linqを支える基本的なC#の拡張の説明(わかりやすい)
LINQ の進化の過程と C# のデザインへの影響
DLinqやXLinq以外でどのようにLinqを実装するかの説明
How to implement IQueryable (Part 1)
- 作者: Fabrice Marguerie,Steve Eichert,Jim Wooley
- 出版社/メーカー: Manning Publications
- 発売日: 2008/02/14
- メディア: ペーパーバック
- クリック: 5回
- この商品を含むブログ (4件) を見る
Introducing LINQ
追加
LINQ to SQL
Part 1: Introduction to LINQ to SQL
Part 2: Defining our Data Model Classes
Part 3: Querying our Database
Part 4 - Updating our Database
疑問
Labmda Expression と Anonymous Method の違いで書かれているTOP 1の最適化はどのように行っているか、
以下記事の抜粋。
例えは、DLINQ で以下のクエリを書きます。 db.Log = Console.Out; var q1 = db.Customers. Where(c => c.City == "London"). Select(c => new {c.City}); var r1 = q1.First(); 上のクエリでDLINQがサーバに投げるSQL Queryは SELECT TOP 1 [t0].[City] FROM [Customers] AS [t0] WHERE [t0].[City] = @p0 では、同じようなクエリを Anonymous Method を使って書いてみます。 var q2 = db.Customers. Where(delegate(Customer c) { return c.City == "London"; }). Select(c => new { c.City }); var r2 = q2.First(); サーバに投げるSQL Queryは SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax] FROM [Customers] AS [t0]
Expression TreeにはFirstの情報はないから、Firstメソッドで最適化するしかないように思うのだが...であれば、Anonymous Methodでも1件しかとらないはず、そもそも観点がWhere句の話かな?...
1年前以上の情報なので変わっているかもしれないので、もう少し調査が必要としとくか。
単に、Anonymous Methodを利用した場合、Expression Treeのように式をデータとして扱えないから、C#で指定された条件からSelect文を作成できないよという意図かな
追記
上記は実行したら指摘の通り動く。後者はWhere句がExpression TreeでないのでSQL文に変換できないため、全検索を行って、あとはObject to LINQで処理しているからなんだろうと。遅延実行とかするので実際は少し違うけど、LINQの動作としてはパイプラインのようなイメージを想像するとよいかも。
ちなみに、デリゲートのWhereの前にWhere句を指定するとそのWhereはSQLで有効になります。
var q2 = context.Products. Where(pp => pp.Title != "X"). Where(delegate(Product pp) { return pp.Title != "X"; }). Select(pp => new { pp.Title }); var r2 = q2.First(); SELECT [t0].[Type], [t0].[Title], [t0].[ProductID], [t0].[Price], [t0].[Size] FROM [dbo].[Products] AS [t0] WHERE [t0].[Title] <> @p0 -- @p0: Input NVarChar (Size = 1; Prec = 0; Scale = 0) NOT NULL [X] SqlProvider\AttributedMetaModel
あと、TOP 1の最適は、FirstのメソッドでExpression TreeにTOPに当たる式を追加すれば可能ですね。