Asp.net(c#)自定义分页存储过程 - 分页期间性能不佳

时间:2011-06-09 19:15:18

标签: asp.net

我有一个asp:GridView,数据源像List 当我使用MS SERVER Management中的过程

时,我使用过程添加了自定义分页

Studio的性能很快,只要我在asp.net中尝试它,性能就很糟糕

分页。 第一步(当gridview填充时)非常快,但是当我开始分页时,

表演杀死,我等待5-25秒传递到下一页。

亲爱的,我必须做些什么来解决这个问题,你能帮助我吗?

这是存储过程

CREATE PROCEDURE [sp_QS]
@startRowIndex INT,
@maximumRows INT,
@afterWhere NVARCHAR(MAX),
@sortBy NVARCHAR(MAX),
@totalRows INT OUT
AS

SET NOCOUNT ON;

DECLARE @P NVARCHAR(MAX), @Q1 NVARCHAR(MAX), @Q2 NVARCHAR(MAX)
DECLARE @first_id INT

SET @startRowIndex = (@startRowIndex - 1) * @maximumRows

SET @Q1 = 'query part 1'

SET @Q2 = 'query part 2'

IF @startRowIndex = 0
BEGIN
SET @startRowIndex = 1
END

SET ROWCOUNT @startRowIndex
SET @P = 'SET NOCOUNT ON;     DECLARE @out INT     SELECT @out = id FROM table1 ' + @Q2 + ' 

WHERE ' + @afterWhere + '     SELECT @out'

IF OBJECT_ID('tempdb..#t1','u') IS NOT NULL
BEGIN
DROP TABLE #t1
END
CREATE TABLE #t1 (col INT)
INSERT #t1 EXEC(@P)
SELECT @first_id = col FROM #t1
DROP TABLE #t1

--SELECT @first_id AS FFFF --PRINT @first_id

SET ROWCOUNT @maximumRows
SET @P = 'SET NOCOUNT ON;' + 'SELECT ' + @Q1 + ' FROM table ' + @Q2 + ' WHERE (id >=' + 

CAST(@first_id AS NVARCHAR(60)) + ') AND (' + @afterWhere + ') ' + @sortBy
EXEC(@P)

SET ROWCOUNT 0

-- GET THE TOTAL ROWS
IF @startRowIndex = 1
BEGIN
SET @P = 'SET NOCOUNT ON;' + 'SELECT COUNT(id) FROM table1 ' + @Q2 + ' WHERE ' + 

@afterWhere
IF OBJECT_ID('tempdb..#t2','u') IS NOT NULL
BEGIN
DROP TABLE #t2
END
CREATE TABLE #t2 (col INT)
INSERT #t2 EXEC (@P)
SELECT @totalRows = col FROM #t2
DROP TABLE #t2
SELECT @totalRows AS QueryResultRowCount
END

GO

此处是ASP.NET中的代码(使用C#)

private void BindData()
{
    string connectionString = "Server=localhost;" + 
           "Database=Northwind;Trusted_Connection=true";
    SqlConnection myConnection = new SqlConnection(connectionString);
    SqlCommand myCommand = new SqlCommand("usp_GetProducts", 
                                           myConnection);
    myCommand.CommandType = CommandType.StoredProcedure;

    myCommand.Parameters.AddWithValue("@startRowIndex", 
                                      currentPageNumber);
    myCommand.Parameters.AddWithValue("@maximumRows", PAGE_SIZE);
    myCommand.Parameters.Add("@totalRows", SqlDbType.Int, 4);
    myCommand.Parameters["@totalRows"].Direction = 
                       ParameterDirection.Output;

    SqlDataReader sqlReader = myCommand.ExecuteReader();

    while(sqlReader.Read())
    {
        // filling List<> object to bind to gridview as datasource
    }
...
}

我必须按下'next'和'prvious',按下这些按钮,我正在改变

currentPageNumber with +或 - 1,之后调用BindData()方法。

提前致谢

1 个答案:

答案 0 :(得分:0)

这是SQL Server 2005示例中针对AdventureWorks数据库的SQL:

    DECLARE 
    @FirstRow int,
    @LastRow int,
    @Sorting varchar(50);

Declare @SelectClause nvarchar(max),
        @Params nvarchar(MAX);

SELECT @FirstRow = 1, @LastRow = 10;

SELECT @SelectClause = 'WITH CTE AS (
SELECT 
    ROW_NUMBER() OVER ( ORDER BY ' + COALESCE(@Sorting, 'SalesOrderID ASC') + ' ) AS RowNumber,
    COUNT(*) OVER() AS TotalRows,
    SalesOrderID,
    OrderDate,
    DueDate,
    CASE OnlineOrderFlag WHEN 1 THEN ''Yes'' ELSE ''No'' END as OnlineOrderFlagString
FROM 
    Sales.SalesOrderHeader
WHERE
    SubTotal > 100)

SELECT * FROM CTE WHERE RowNumber >= @FirstRow AND RowNumber < @LastRow',
@Params = '@FirstRow int, @LastRow int';

exec sp_executesql 
    @statement = @SelectClause,
    @params = @Params,
    @FirstRow = @FirstRow,
    @LastRow = @LastRow;

执行查询后,如果存在,则可以从第一行获取总行数值。请注意,如果您必须提供按计算列(如OnlineOrderFlagString)排序的能力,则查询将变得更复杂:

DECLARE 
    @FirstRow int,
    @LastRow int,
    @Sorting varchar(50);

Declare @SelectClause nvarchar(max),
        @Params nvarchar(MAX);

SELECT @FirstRow = 1, @LastRow = 10, @Sorting = 'OnlineOrderFlagString ASC'

SELECT @SelectClause = 'WITH CTE_1 AS (
SELECT 
    SalesOrderID,
    OrderDate,
    DueDate,
    CASE OnlineOrderFlag WHEN 1 THEN ''Yes'' ELSE ''No'' END as OnlineOrderFlagString
FROM 
    Sales.SalesOrderHeader
WHERE
    SubTotal > 100),
CTE_2 AS (
SELECT
    ROW_NUMBER() OVER ( ORDER BY ' + COALESCE(@Sorting, 'SalesOrderID ASC') + ' ) AS RowNumber,
    COUNT(*) OVER() AS TotalRows,
    SalesOrderID,
    OrderDate,
    DueDate,
    OnlineOrderFlagString
FROM
    CTE_1
)

SELECT * FROM CTE_2 WHERE RowNumber >= @FirstRow AND RowNumber < @LastRow',
@Params = '@FirstRow int, @LastRow int';

exec sp_executesql 
    @statement = @SelectClause,
    @params = @Params,
    @FirstRow = @FirstRow,
    @LastRow = @LastRow;