刚刚从 Subsonic 2.2 ActiveRecord 更新到 3.0.0.3。 我正在尝试使用 LINQ 执行这样的分页查找查询(我的对象/表称为“存储库”):
Repository.Find(item => item.DocumentTitle.Contains(searchTerm))
.OrderBy(i => i.DocumentTitle).Skip((currentPage - 1) * itemsPerPage)
.Take(itemsPerPage);
当我使用 SQL Server Profiler 查看此查询生成的 SQL 时,SQL 中没有分页,所有分页都是在 C# 中的内存中完成的。 现在,Subsonic 查询语言确实有一个很好的 GetPaged 过程,它可以正常工作,但我认为 LINQ 也应该执行此操作。 我在这里错过了什么还是这是 LINQ 的限制?
我知道
Repository.GetPaged()
函数,但它没有足够的参数 - 我需要进行动态排序,以及 Find()
。
经过进一步测试,此语句正确运行:
(from i in dataContext.Repositories
where i.DocumentTitle.Contains(searchTerm)
orderby i.DateCreated ascending select i)
.Skip((currentPage - 1) * itemsPerPage).Take(itemsPerPage);
执行时,上面的 linq 语句会在 sql 中正确分页。
我能得出的唯一结论是,当您使用方法链接语法时,一旦超出初始 lamda 表达式
Repository.Find(item => item.DocumentTitle.Contains(searchTerm))
亚音速 SQL 解释器停止为末尾链接的任何方法创建 SQL
.OrderBy(i => i.DocumentTitle).Skip(15).Take(10);
或者,我在这里完全做错了什么吗? 有人有见解吗?
您可以通过在排序字段中添加“desc”来对 GetPaged 进行排序,但是...
分页应该可以工作 - 我正在查看我面前的分页 SQL,它不是在内存中完成的。你如何测试这个?如果您使用“ToList()”来执行查询 - 那么请查看分析器。
有点晚了但是...
Repository.Find()
返回 IList,因此执行查询,因此执行 SQL 时无需分页
.Skip(x).Take(x)
是在内存中完成的。 尝试一下
Repository.All().Where(expression).Skip(x).Take(x)
所有这些都返回 IQueryable,并且没有一个枚举对象,因此分页是使用 ROW_NUMBER() 函数在 SQL 中完成的。
话虽如此,Subsonic 3 简单存储库正在生成以下 SQL
exec sp_executesql N'SELECT [t0].[Id], [t0].[IsDeleted], [t0].[Name], [t0].[ParentUuid], [t0].[Uuid]
FROM ( SELECT [t1].[Id], [t1].[IsDeleted], [t1].[Name], [t1].[ParentUuid], ROW_NUMBER() OVER() AS rownum, [t1].[Uuid]
FROM [Sites] AS t1
WHERE (([t1].[ParentUuid] = @p0) AND ([t1].[IsDeleted] = 0))) AS t0
WHERE [t0].[rownum] BETWEEN (20 + 1) AND (20 + 10)',N'@p0 uniqueidentifier',@p0='00000000-0000-0000-0000-000000000000'
抛出异常
Unhandled Exception: System.Data.SqlClient.SqlException: The ranking function "ROW_NUMBER" must have an ORDER BY clause.
所以 Subsonic 中似乎有一个错误:-(