IQueryable
たとえばFindNewCustomers()
、FindCustomersRegisteredAfter(int year)
LINQ to SQL のクエリを「チェーン」するために使用するC# 拡張メソッドなどがあります。
今私の問題に:私はコンパイルされたクエリを作成したい、例えば:
private static Func<MyDataContext, SearchInfo, IQueryable<Customer>>
CQFindAll =
CompiledQuery.Compile((MyDataContext dc, SearchInfo info) =>
dc.Contacts.Select(c => c).FindCustomersRegisteredAfter(info.RegYear)
.OrderBy(info.OrderInfo)
.Skip(info.SkipCount)
.Take(info.PageSize));
FindCustomersRegisteredAfter(int year)
メソッドは、 を受け取って返す拡張メソッドですIQueryable
。このOrderBy
メソッドは、文字列に基づいて動的な式を作成する拡張メソッド (System.Linq.Dynamic) でもあります (たとえば、"FirstName ASC" はフィールド FirstName を昇順で並べ替えます)。Skip
およびTake
は組み込みメソッドです。
上記(コンパイルされたクエリではなく、通常のクエリ)は完璧に機能します。コンパイルされたクエリに入れると、次のエラーが発生します。
メソッド 'System.Linq.IQueryable`1[Domain.Customer] FindCustomersRegisteredAfter[Customer](System.Linq.IQueryable`1[Domain.Customer], Int32)' には、SQL への変換がサポートされていません。
繰り返しになりますが、クエリがコンパイルされていない場合、これは完全に機能し、通常の LINQ クエリだけです。エラーは、CompiledQuery.Compile() 内にある場合にのみ表示されます。
ヘルプ??!
編集: var query = (...) CompiledQuery.Compile の内部と同じ方法でクエリを作成すると、次の SQL が生成されます。
SELECT [t1].[Id], [t1].[FirstName], [t1].[LastName],
[t1].[RegYear], [t1].[DeletedOn]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[LastName]) AS [ROW_NUMBER],
[t0].[Id], [t0].[FirstName], [t0].[LastName], [t0].[RegYear],
[t0].[DeletedOn]
FROM [dbo].[Contacts] AS [t0]
WHERE ([t0].[RegYear] > @p0) AND ([t0].[DeletedOn] IS NULL)
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p1 + 1 AND @p1 + @p2
ORDER BY [t1].[ROW_NUMBER]
これで、SQL はすべて完全に変換可能であることがわかります。これを繰り返し実行するには、@p0、@p1、および @p2 を入力するだけで済みます。CompiledQuery.Compile の何が問題になっていますか?!?
更新: OrderBy が機能しないことを理解しています (@p パラメータではないため)。ただし、 CompiledQuery.Compile が拡張メソッドで機能しない理由をまだ理解しようとしています。このトピックに関するインターネット上の情報は事実上存在しません。