我在IQueryable
上有C#扩展方法,例如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。
再次强调,如果查询是非编译的,它可以正常工作。这个错误只会在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一起使用。对于这个主题,网上的信息几乎不存在。