我有 C# 扩展方法IQueryable
,例如FindNewCustomers()
等等FindCustomersRegisteredAfter(int year)
,我使用这些方法将 LINQ to SQL 的查询“链接”在一起。
现在我的问题:我想创建编译查询,例如:
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 不能与我的扩展方法一起使用。互联网上有关该主题的信息几乎不存在。