Linq関連の記事のメモ

LinqをORMとして見た時の最適化(カスタマイズ)ってできるのか興味があるので少しLinqの実装を調査し始めました。
Linqも最近はいろいろ情報がでてきてなんとなくイメージがわかるのですがまだまだクリアになっていません。特にクエリ式(Query Expression)の実装部分がSQL文生成に大きく絡んでいるようなのですが、その部分の構造をもう少し理解する必要がありそうです。


とりあえず、リンクをメモっておきます。

Linqを支える基本的なC#の拡張の説明(わかりやすい)
LINQ の進化の過程と C# のデザインへの影響


DLinqやXLinq以外でどのようにLinqを実装するかの説明
How to implement IQueryable (Part 1)


C#3.0の仕様書


LINQ in Action

LINQ in Action

一部オンラインで公開されているようです。予約するかな。
Introducing LINQ

疑問

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に当たる式を追加すれば可能ですね。