SQL Server 2008 上的 ServiceStack ORMLite 分页

问题描述

我有一个现有的 sql Server 2008 数据库,其中包含许多视图、存储过程和函数

我希望能够从这些 sql 函数之一中SELECT 数据并限制它在分页方案中返回的行数。

我尝试将 .Select.Skip.Take 结合使用,如下所示:

        public IEnumerable<Product> CallsqlFunction_dbo_Search_Products_View(int clientId,string environmentCode,int sessionId)
        {
            IEnumerable<Product> results;

            using (var db = _dbConnectionFactory.open())
            {
                results = db.Select<Product>(@"
                    SELECT
                        * 
                    FROM 
                        [dbo].[Search_Products_View]
                        (
                            @pClientID,@pEnvironmentCode,@pSessionId
                        )",new
                    {
                        pClientID = clientId,pEnvironmentCode = environmentCode,pSessionId = sessionId
                    })
                    .Skip(0)
                    .Take(1000);

                db.Close();
            }

            return results;
        }

这将生成sql Server 上执行的以下 sql

exec sp_executesql N'
                    SELECT
                        * 
                    FROM 
                        [dbo].[Search_Products_View]
                        (
                            @pClientID,@pSessionId
                        )',N'@pClientID int,@pEnvironmentCode varchar(8000),@pSessionId int',@pClientID=0,@pEnvironmentCode='LIVE',@pSessionId=12345

这意味着此查询返回 134,000 个产品,而不是我期望的 1000 个的第一页。一旦 sql Server 返回 134,000 行,就会在 API 服务器上进行分页

是否可以使用 Ormlite 以便我可以使用它在查询生成类似于以下内容分页

exec sp_executesql N'
SELECT
    [t1].*
FROM (
    SELECT
        ROW_NUMBER() OVER (ORDER BY [t0].[ProductId],[t0].[ProductName])
    FROM
        [dbo].[Search_Products_View](@pClientId,@pSessionId) AS [t0]
    WHERE
        (LOWER([t0].[ProductStatus]) = @pProductStatus1) OR (LOWER([t0].[ProductStatus]) = @pProductStatus2) OR (LOWER([t0].[ProductStatus]) = @pProductStatus3)
    ) AS [t1]
WHERE 
    [t1].[ROW_NUMBER] BETWEEN @pPageNumber + 1 AND @pPageNumber + @pNumberOfRowsPerPage
ORDER BY [t1].[ROW_NUMBER]',N'@pClientId decimal(9,0),@pEnvironmentCode char(3),@pSessionId decimal(9,@pProductStatus1 varchar(8000),@pProductStatus2 varchar(8000),@pProductStatus3 varchar(8000),@pPageNumber int,@pNumberOfRowsPerPage int',@pClientId=0,@pSessionId=12345,@pProductStatus1='1',@pProductStatus2='2',@pProductStatus3='3',@pPageNumber=0,@pNumberOfRowsPerPage=1000

解决方法

OrmLite 将在

如果您经常这样做,我建议您将窗口函数 SQL 模板包装在扩展方法中,以便您可以在自定义查询中轻松使用它,例如:

results = db.Select<Product>(@"
    SELECT
        * 
    FROM 
        [dbo].[Search_Products_View]
        (
            @pClientID,@pEnvironmentCode,@pSessionId
        )"
    .InWindowingPage(0,1000),new
    {
        pClientID = clientId,pEnvironmentCode = environmentCode,pSessionId = sessionId
    })

如果你想使用 DB Params 作为偏移量,你需要一些耦合来使用传统的参数名称:

results = db.Select<Product>(@"
    SELECT
        * 
    FROM 
        [dbo].[Search_Products_View]
        (
            @pClientID,@pSessionId
        )"
    .InWindowingPage(),pSessionId = sessionId,pPageNumber = 0,pNumberOfRowsPerPage = 100
    })