CodeSmith Community
Your Code. Your Way. Faster!

Paging and Custom Stored Procedure Example

Latest post 08-24-2008 12:55 PM by macros. 4 replies.
  • 05-08-2007 3:32 PM

    • Junto
    • Top 500 Contributor
    • Joined on 01-30-2007
    • Posts 12
    • Points 390

    Paging and Custom Stored Procedure Example

    Hi,

    Would anyone like to share an example of a custom stored procedure that:

    • Supports paging, and
    • Returns a TList not a dataset, and
    • INNER JOINS on one or more sub tables so a WHERE search can target the sub tables

    I have the following, which is an exact copy of the same generated GetPaged SP for a table called "Company", but with two INNER JOINS across tables that are related by foreign keys:

    ALTER PROCEDURE [dbo].[_Company_SearchGetPaged]
    (
    @WhereClause varchar (2000) = null ,
    @OrderBy varchar (2000) = null ,
    @PageIndex int = null ,
    @PageSize int = null
    )
    AS

    BEGIN

    DECLARE @PageLowerBound int
    DECLARE @PageUpperBound int

    -- Set the page bounds
    SET @PageLowerBound = @PageSize * @PageIndex
    SET @PageUpperBound = @PageLowerBound + @PageSize

    IF (@OrderBy is null or LEN(@OrderBy) < 1)
    BEGIN
    -- default order by to first column
    SET @OrderBy = '[CompanyID]'
    END

    -- SQL Server 2005 Paging
    declare @SQL as nvarchar(4000)
    SET @SQL = 'WITH PageIndex AS ('
    SET @SQL = @SQL + ' SELECT'
    IF @PageSize > 0
    BEGIN
    SET @SQL = @SQL + ' TOP ' + convert(nvarchar, @PageUpperBound)
    END

    SET @SQL = @SQL + ' ROW_NUMBER() OVER (ORDER BY ' + @OrderBy + ') as RowIndex'
    SET @SQL = @SQL + ', [Company].[CompanyID]'
    SET @SQL = @SQL + ', [Company].[AccountID]'
    SET @SQL = @SQL + ', [Company].[CompanyName]'
    SET @SQL = @SQL + ', [Company].[ContactName]'
    SET @SQL = @SQL + ', [Company].[DateCreated]'
    SET @SQL = @SQL + ', [Company].[PhoneNumber]'
    SET @SQL = @SQL + ', [Company].[Website]'
    SET @SQL = @SQL + ', [Company].[EmailAddress]'
    SET @SQL = @SQL + ', [Company].[AddressID]'
    SET @SQL = @SQL + ', [Company].[Active]'
    SET @SQL = @SQL + ' FROM dbo.[Company]'

    SET @SQL = @SQL + ' INNER JOIN [Subscription] ON [Subscription].CompanyID = [Company].CompanyID'
    SET @SQL = @SQL + ' INNER JOIN [Tag] ON [Tag].TagID = [Subscription].TagID'

    IF LEN(@WhereClause) > 0
    BEGIN
    SET @SQL = @SQL + ' WHERE ' + @WhereClause
    END

    SET @SQL = @SQL + ' ) SELECT'
    SET @SQL = @SQL + ' [CompanyID],'
    SET @SQL = @SQL + ' [AccountID],'
    SET @SQL = @SQL + ' [CompanyName],'
    SET @SQL = @SQL + ' [ContactName],'
    SET @SQL = @SQL + ' [DateCreated],'
    SET @SQL = @SQL + ' [PhoneNumber],'
    SET @SQL = @SQL + ' [Website],'
    SET @SQL = @SQL + ' [EmailAddress],'
    SET @SQL = @SQL + ' [AddressID],'
    SET @SQL = @SQL + ' [Active]'
    SET @SQL = @SQL + ' FROM PageIndex'
    SET @SQL = @SQL + ' WHERE RowIndex > ' + convert(nvarchar, @PageLowerBound)

    IF @PageSize > 0
    BEGIN
    SET @SQL = @SQL + ' AND RowIndex <= ' + convert(nvarchar, @PageUpperBound)
    END

    SET @SQL = @SQL + ' ORDER BY ' + @OrderBy
    exec sp_executesql @SQL

    -- get row count
    SET @SQL = 'SELECT COUNT(*) as TotalRowCount'
    SET @SQL = @SQL + ' FROM dbo.[Company]'

    SET @SQL = @SQL + ' INNER JOIN [Subscription] ON [Subscription].CompanyID = [Company].CompanyID'
    SET @SQL = @SQL + ' INNER JOIN [Tag] ON [Tag].TagID = [Subscription].TagID'

    IF LEN(@WhereClause) > 0
    BEGIN
    SET @SQL = @SQL + ' WHERE ' + @WhereClause
    END

    exec sp_executesql @SQL

    END

    The generated method that .netTiers generates returns a void:

    public virtual void SearchGetPaged( System.String whereClause, System.String orderBy, System.Int32? pageIndex, System.Int32? pageSize, int start, int pageLength)

    How on earth do you get the data out from this method??? I'm able to do the following, but can't assign the result to TList<Company> and bind the data to the GridView because the method does't return anything:

    DataRepository.CompanyProvider.SearchGetPaged("Tag.Name LIKE '%software%'", null, GridViewSearch.PageIndex, GridViewSearch.PageSize);

    Any suggestions, or even better code examples from people who have solved this problem are most welcome!

    Please help, I'm really stuck. Should I be using a view instead for this kind of thing? I can get this to work without the paging, but with 1000's of records a lack of paging is going to cause me some serious problems!

    Thanks in advance.

    Ben

    • Post Points: 35
  • 05-08-2007 4:07 PM In reply to

    • swin
    • Top 10 Contributor
    • Joined on 06-14-2006
    • London, UK
    • Posts 924
    • Points 34,750

    Re: Paging and Custom Stored Procedure Example

    Ben,

    Problem is caused by using dynamic sql - codesmith can't determine the output.

    see here for a workaround - http://community.codesmithtools.com/forums/permalink/23552/24140/ShowThread.aspx#24140

    hth

    swin

    ------------------------------------------------- Member of the .NetTiers team -------------------------------------------------
    • Post Points: 5
  • 05-10-2007 10:42 AM In reply to

    • Junto
    • Top 500 Contributor
    • Joined on 01-30-2007
    • Posts 12
    • Points 390

    Re: Paging and Custom Stored Procedure Example

    I have had some success in solving this problem. The ORDER BY still eludes me, but I think a series of CASE WHEN statements would work (although ugly):

    ALTER PROCEDURE [dbo].[_Company_SearchGetPaged]
    (
    @WhereClause varchar (2000) = null ,
    @PageIndex int = null ,
    @PageSize int = null
    )
    AS

    BEGIN

    -- SQL Server 2005 Paging
    WITH PageIndex AS (
    SELECT ROW_NUMBER() OVER (ORDER BY CompanyName) AS
    RowIndex
    ,
    [Company].[CompanyID],
    [Company].[AccountID],
    [Company].[CompanyName],
    [Company].[ContactName],
    [Company].[DateCreated],
    [Company].[PhoneNumber],
    [Company].[Website],
    [Company].[EmailAddress],
    [Company].[AddressID],
    [Company].[Active]
    FROM dbo.[Company]
    INNER JOIN [Subscription] ON [Subscription].CompanyID = [Company].CompanyID
    INNER JOIN [Tag] ON [Tag].TagID = [Subscription].TagID
    WHERE Tag.[Name] IN (SELECT [Value] FROM dbo.Split(@WhereClause,','))
    GROUP BY
    [Company].[CompanyID],
    [Company].[AccountID],
    [Company].[CompanyName],
    [Company].[ContactName],
    [Company].[DateCreated],
    [Company].[PhoneNumber],
    [Company].[Website],
    [Company].[EmailAddress],
    [Company].[AddressID],
    [Company].[Active]
    )
    SELECT
    [CompanyID],
    [AccountID],
    [CompanyName],
    [ContactName],
    [DateCreated],
    [PhoneNumber],
    [Website],
    [EmailAddress],
    [AddressID],
    [Active]
    FROM PageIndex
    WHERE RowIndex BETWEEN (@PageIndex - 1) * @PageSize + 1 and @PageIndex*@PageSize
    ORDER BY CompanyName

    -- get row count
    SELECT COUNT(DISTINCT Company.CompanyID)
    FROM dbo.[Company]
    INNER JOIN [Subscription] ON [Subscription].CompanyID = [Company].CompanyID
    INNER JOIN [Tag] ON [Tag].TagID = [Subscription].TagID
    WHERE Tag.[Name] IN (SELECT [Value] FROM dbo.Split(@WhereClause,','))

    END

    The Split function is quite well explained here: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648

    Hopefully this helps anyone else undertaking paging with custom stored procedures. This returns a TList<Company> as required.

    Regards

    Ben

    • Post Points: 35
  • 04-27-2008 3:35 AM In reply to

    • vjerko
    • Top 500 Contributor
    • Joined on 04-27-2008
    • Posts 10
    • Points 80

    Re: Paging and Custom Stored Procedure Example

    Well.. i have done the same - except there will be no search bar in the nettiers grid, and there will be no where clause. I don't see the way to implement this without dynamic sql.

    Just one note for readers (i lost too much time on this) - u need to refresh code smith cache by clicking tables collection and selecting the same again)

    And yes.. i think it would be the best to impletemnt some xml configuration file. You would put a class path and nettiers would generate method wrapper. Like, it would be cool to have ability to have wrapped methods like stats or something like that in some different layer not related to table, like @@CPU_BUSY, or some utility like deleting old records. Well, dynamic SQL is must have and this is big disadvantage.

    • Post Points: 35
  • 08-24-2008 12:55 PM In reply to

    • macros
    • Not Ranked
    • Joined on 08-06-2008
    • Posts 3
    • Points 75

    Re: Paging and Custom Stored Procedure Example

    Reply |Contact |Answer

    Hi,

    I realise this thread is probably long dead and buried however thought I would throw in my comments for anyone who stumbles across it - dynamic sql can be used in custom SPs, you just need to make sure that records are inserted into a temp table / table variable and then selected from this to allow nettiers to discover the definition.  For example:

    original SP:

    select ID,
             Task,
             Comments
    from Tasks
    order by.....

    rewrite to:

    declare @Tasks as Table ( -- Must be same definition as original table
        ID int,
        Task varchar(100),
        Comments varchar(100)
    )

    declare @sql as nvarchar(max)
    set @sql = 'dynamic sql here'

    insert into @Tasks
    exec sp_executesql @sql

    I've successfully used this method to implement paging and sorting in custom stored procs (although cuurrently have a quick and nasty fix in overriding the custom method in the service class in order to always set start to zero, but that's another story.....)

     

    • Post Points: 5
Page 1 of 1 (5 items) | RSS
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems