silverlight + wcf(json格式) + sqlserver存储过程分页

silverlight并没有提供现成的分页控件,百度了一圈,也没有发现aspx中好用的类似AspNetPager成熟控件,网上现有的一些分页代码,很多也是基于1.0版本的,silverlight2.0的并不多,自个儿琢磨了一下,发现自己弄一个也并非难事,思路和主要代码分享如下:

1.通用的“海量”数据分页存储过程
在做aspx开发时我已经用存储过程分页多年,这个东东是通用的(不管前端用什么语言来做),而且性能也不错,所以这里就直接套过来用了,百度一下"分页存储过程"会有N多版本,这里也给出我自己写的一个版本(仅适用于sqlserver 2005及以上版本)

分页存储过程
-- =============================================
-- Author:        <杨俊明-菩提树下的杨过>
-- Create date: <2006-11-05>
-- Description:    <高效分页存储过程,仅适用于Sql2005>
-- Notes:        <排序字段强烈建议建索引>
-- =============================================
CREATE Procedure [dbo].[up_Page2005] 
 @TableName varchar(500),        --表名
 @Fields nvarchar(MAX) = '*',    --字段名(全部字段为*)
 @OrderField nvarchar(MAX),        --排序字段(必须!支持多字段)
 @sqlWhere nvarchar(MAX) = Null,--条件语句(不用加where)
 @pageSize int,                    --每页多少条记录
 @pageIndex int = 1 ,            --指定当前为第几页
 @TotalPage int output            --返回总页数 
as
begin

    Begin Tran --开始事务

    Declare @sql nvarchar(MAX);
    Declare @totalRecord int;    

    --计算总记录数
         
    if (@SqlWhere='' or @sqlWhere=NULL)
        set @sql = 'select @totalRecord = count(*) from ' + @TableName
    else
        set @sql = 'select @totalRecord = count(*) from ' + @TableName + ' where ' + @sqlWhere

    

    EXEC sp_executesql @sql,N'@totalRecord int OUTPUT',@totalRecord OUTPUT--计算总记录数        
    
    --计算总页数
    select @TotalPage=CEILING((@totalRecord+0.0)/@PageSize)

    if (@SqlWhere='' or @sqlWhere=NULL)
        set @sql = 'Select * FROM (select ROW_NUMBER() Over(order by ' + @OrderField + ') as RowId,' + @Fields + ' from ' + @TableName + ' with (nolock)' 
    else
        set @sql = 'Select * FROM (select ROW_NUMBER() Over(order by ' + @OrderField + ') as RowId,' + @Fields + ' from ' + @TableName + ' with (nolock) where ' + @SqlWhere    
        
    
    --处理页数超出范围情况
    if @PageIndex<=0 
        Set @pageIndex = 1
    
    if @pageIndex>@TotalPage
        Set @pageIndex = @TotalPage

     --处理开始点和结束点
    Declare @StartRecord int
    Declare @EndRecord int
    
    set @StartRecord = (@pageIndex-1)*@PageSize + 1
    set @EndRecord = @StartRecord + @pageSize - 1

    --继续合成sql语句
    set @Sql = @Sql + ') as ' + @TableName + ' where RowId between ' + Convert(varchar(50),@StartRecord) + ' and ' +  Convert(varchar(50),@EndRecord)
    print @sql ;
    Exec(@Sql)
    ---------------------------------------------------
    If @@Error <> 0
      Begin
        RollBack Tran
        Return -1
      End
    Else
      Begin
        Commit Tran
        Return @totalRecord ---返回记录总数
      End
end

  

Code
-- =============================================
-- Author:        <杨俊明-菩提树下的杨过>
-- Create date: <2006-11-05>
-- Description:    <高效分页存储过程,仅返回总页数和总记录数,仅适用于Sql2005>
-- Notes:        <排序字段强烈建议建索引>
-- =============================================
CREATE Procedure [dbo].[up_Page2005_Statistic] 
 @TableName varchar(500),        --表名
 @Fields nvarchar(MAX) = '*',    --字段名(全部字段为*)
 @OrderField nvarchar(MAX),        --排序字段(必须!支持多字段)
 @sqlWhere nvarchar(MAX) = Null,--条件语句(不用加where)
 @pageSize int,                    --每页多少条记录
 @pageIndex int = 1 ,            --指定当前为第几页
 @TotalPage int output            --返回总页数 
as
begin   

    Declare @sql nvarchar(MAX);
    Declare @totalRecord int;    

    --计算总记录数         
    if (@SqlWhere='' or @sqlWhere=NULL)
        set @sql = 'select @totalRecord = count(*) from ' + @TableName
    else
        set @sql = 'select @totalRecord = count(*) from ' + @TableName + ' where ' + @sqlWhere    

    EXEC sp_executesql @sql,N'@totalRecord int OUTPUT',@totalRecord OUTPUT--计算总记录数        
    
    --计算总页数
    select @TotalPage=CEILING((@totalRecord+0.0)/@PageSize)   
    

    print 'TotalRecord=' + Convert(nvarchar(50),@totalRecord);
    print 'TotalPage=' + Convert(nvarchar(50),@totalPage);

    Return @totalRecord ---返回记录总数
end

 

注:第二个是直接在第一个基础上简化得来的,仅返回总页数和总记录数;方便某些不需要返回实体数据,仅需要知道总页数和总记录数的特殊情况调用

2.利用wcf直接或间接调用存储过程,返回json数据

wcf能返回json数据已经不是什么新鲜事儿了,这里就不多说了,贴出主要代码(直接拿我以前封装好的工具库中的一个方法示例一下,大家知道意思就可以了) 

Code
/// <summary>
        /// 调用分页存储过程,返回Json数据
        /// </summary>
        /// <param name="pTable"></param>
        /// <param name="pWhere"></param>
        /// <param name="pFields"></param>
        /// <param name="pOrder"></param>
        /// <param name="pPageSize"></param>
        /// <param name="pPageIndex"></param>
        /// <param name="pTotalPage"></param>
        /// <param name="pTotalRecord"></param>
        /// <returns></returns>
        [WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, UriTemplate = "SelectPageData?pTable={pTable}&pWhere={pWhere}&pFields={pFields}&pOrder={pOrder}&pPageSize={pPageSize}&pPageIndex={pPageIndex}&pTotalPage={pTotalPage}&pTotalRecord={pTotalRecord}")]
        [OperationContract]
        public Stream SelectPageData(string pTable, string pWhere, string pFields, string pOrder, int pPageSize,int pPageIndex,int pTotalPage,int pTotalRecord)
        {            
            return GetStream(GetJsonData(Database.GetDataTableForPage(pTable,pFields,pOrder,pWhere,pPageSize,pPageIndex,pTotalPage,pTotalRecord)));
        }

        /// <summary>
        /// 调用分页存储过程,返回总页数和总记录数
        /// </summary>
        /// <param name="pTable"></param>
        /// <param name="pWhere"></param>
        /// <param name="pFields"></param>
        /// <param name="pOrder"></param>
        /// <param name="pPageSize"></param>
        /// <param name="pPageIndex"></param>
        /// <param name="pTotalPage"></param>
        /// <param name="pTotalRecord"></param>
        /// <returns></returns>
        [WebInvoke(Method = "*", ResponseFormat = WebMessageFormat.Json, UriTemplate = "SelectPageDataStatistic?pTable={pTable}&pWhere={pWhere}&pFields={pFields}&pOrder={pOrder}&pPageSize={pPageSize}&pPageIndex={pPageIndex}&pTotalPage={pTotalPage}&pTotalRecord={pTotalRecord}")]
        [OperationContract]
        public Stream SelectPageDataStatistic(string pTable, string pWhere, string pFields, string pOrder, int pPageSize, int pPageIndex, int pTotalPage, int pTotalRecord)
        {
           Database.GetTotalPageAndTotalRecordForPage(pTable, pFields, pOrder, pWhere, pPageSize, pPageIndex, out pTotalPage,out pTotalRecord);
           string _Result = "{'TotalPage':'" + pTotalPage.ToString() + "','RecordCount':'" + pTotalRecord + "'}";
           return GetStream(_Result);
        }

 其中有二个方法GetStream和GetJsonData,主要用于将字符串转换为流,以及将格式化Json字符串 

Code
private Stream GetStream(string str)
        {
            MemoryStream ms = new MemoryStream();
            StreamWriter sw = new StreamWriter(ms);
            sw.AutoFlush = true;
            sw.Write(str);
            ms.Position = 0;
            WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
            return ms;
        }

        public static string GetJsonData(DataTable dt)
        {
            string _Result = Utils.CreateJsonParameters(dt);//CreateJsonParameters是我工具库里的一个方法,用于将DataTable转化为json字符串

            if (_Result.IsNullStr())
            {
                _Result = "[{}]";
            }
            else
            {
                if (_Result.StartsWith("{ \"Head\":["))
                {
                    _Result = _Result.Replace("{ \"Head\":[", "[");
                }

                if (_Result.EndsWith("]}")) 
                {
                    _Result = _Result.Trim("}");
                }
            }           
            return _Result;
        }

 

3.前面二步弄完了,基本上就可以动手写silverlight代码了

xaml前端文件:

Code
<UserControl
   
    xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
    xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  
    x:Class="WcfTest.DataGrid"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    >
   

    <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="False">
        <Grid.RowDefinitions>
            <RowDefinition>                
            </RowDefinition>
            <RowDefinition Height="25">
            </RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition>
                
            </ColumnDefinition>
            <ColumnDefinition>

            </ColumnDefinition>
        </Grid.ColumnDefinitions>
        
        <data:DataGrid x:Name="dg" AutoGenerateColumns="False" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2">
            <data:DataGrid.Columns>
                <data:DataGridTextColumn Header="F_ID"
                Binding="{Binding F_ID}" />
                <data:DataGridTextColumn Header="F_ClassName" 
                Binding="{Binding F_ClassName}" />
                <data:DataGridTextColumn Header="F_RootId" 
                Binding="{Binding F_RootId}" />
                <data:DataGridTextColumn Header="F_Depth" 
                Binding="{Binding F_Depth}" />
                <data:DataGridTextColumn Header="F_Type" 
                Binding="{Binding F_Type}" />

                
            </data:DataGrid.Columns>
        </data:DataGrid>
        
        <TextBlock x:Name="txtStat" Text="共有X条记录,第X页/共X页,X/每页" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Margin="5,0,0,0" ></TextBlock>
        <StackPanel Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center" Height="22">
            <Button x:Name="btnFirst" Content="首页" Click="btnFirst_Click" ></Button>
            <Button x:Name="btnPrev" Content="上页" Margin="5,0,0,0" Click="btnPrev_Click"></Button>
            <Button x:Name="btnNext" Content="下页" Margin="5,0,0,0" Click="btnNext_Click"></Button>
            <Button x:Name="btnLast" Content="末页" Margin="5,0,0,0" Click="btnLast_Click" ></Button>
            <TextBox x:Name="txtPageIndex" Text="1" Margin="5,0,0,0" Width="30" KeyUp="txtPageIndex_KeyUp"></TextBox>
            <Button x:Name="btnPageGo" Content="Go" Margin="5,0,5,0" Click="btnPageGo_Click"></Button>
        </StackPanel>
    </Grid>
</UserControl>

 

讲解一下:用Grid布局,先分上下二行,第一行放一个DataGrid控件(silverlight2新增的控件!),第二行分二列,左列显示统计信息,右列显示翻页按钮 

后端cs代码: 

Code
using System;
using System.Collections.Generic;
using System.Json;
using System.Net;
using System.Windows.Controls;
using System.Windows.Media;
using JIMMY.TOOLS.Silverlight;

namespace WcfTest
{
    public partial class DataGrid : UserControl
    {

        protected string pTable = "", pWhere = "", pFields = "", pOrderField = "", pBaseUri = "http://localhost:7055/Demo.svc/";
        protected int pPageSize = 10, pPageIndex = 1, pTotalPage = 0, pTotalRecord = 0;

        public DataGrid()
        {
            InitializeComponent();

            #region 初始化查询参数
            pTable = "T_Class";
            //pWhere = "F_Type='place' And F_Depth=0";
            pWhere = "";
            pFields = "F_ID,F_ClassName,F_Depth,F_RootId,F_Type";
            pOrderField = "F_RootId";            
            #endregion 

            //开始查询
            LoadData();
            LoadDataStatistic();

        }

        /// <summary>
        /// 加载分页数据
        /// </summary>
        void LoadData()
        {
           

            Uri serviceUri = new Uri(pBaseUri + "SelectPageData?pTable=" + pTable.UrlEncode() + "&pWhere=" + pWhere.UrlEncode() + "&pFields=" + pFields.UrlEncode() + "&pOrder=" + pOrderField.UrlEncode() + "&pPageSize=" + pPageSize.ToString().UrlEncode() + "&pPageIndex=" + pPageIndex.ToString().UrlEncode() + "&pTotalPage=" + pTotalPage.ToString().UrlEncode() + "&pTotalRecord=" + pTotalRecord.ToString().UrlEncode());
            WebClient downloader = new WebClient();
            downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(LoadDataCompleted);
            downloader.OpenReadAsync(serviceUri);

            txtStat.Text = "数据加载中";
            txtStat.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
        }

        /// <summary>
        /// 加载分页数据的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LoadDataCompleted(object sender, OpenReadCompletedEventArgs e)
        {

            if (e.Error == null)
            {
                try
                {
                    JsonArray _Arr = (JsonArray)JsonArray.Load(e.Result);

                    List<Data> _List = new List<Data>();
                    for (int i = 0; i < _Arr.Count; i++)
                    {

                        _List.Add(new Data() { F_ClassName = _Arr[i]["F_ClassName"], F_Depth = int.Parse(_Arr[i]["F_Depth"]), F_ID = new Guid(_Arr[i]["F_ID"]), F_RootId = int.Parse(_Arr[i]["F_RootId"]), F_Type = _Arr[i]["F_Type"] });
                    }

                    dg.ItemsSource = _List;

                }
                catch (Exception ex)
                {

                }

            }
            else
            {

            }
        }

        /// <summary>
        /// 加载数据的总页数/总记录条数
        /// </summary>
        void LoadDataStatistic()
        {

            Uri serviceUri = new Uri(pBaseUri + "SelectPageDataStatistic?pTable=" + pTable.UrlEncode() + "&pWhere=" + pWhere.UrlEncode() + "&pFields=" + pFields.UrlEncode() + "&pOrder=" + pOrderField.UrlEncode() + "&pPageSize=" + pPageSize.ToString().UrlEncode() + "&pPageIndex=" + pPageIndex.ToString().UrlEncode() + "&pTotalPage=" + pTotalPage.ToString().UrlEncode() + "&pTotalRecord=" + pTotalRecord.ToString().UrlEncode());
            WebClient downloader = new WebClient();
            downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(LoadDataStatisticCompleted);
            downloader.OpenReadAsync(serviceUri);

        }

        /// <summary>
        /// 加载数据的总页数/总记录条数--回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void LoadDataStatisticCompleted(object sender, OpenReadCompletedEventArgs e)
        {

            if (e.Error == null)
            {
                try
                {
                    JsonValue _json = JsonObject.Load(e.Result);                  

                    pTotalPage = int.Parse(_json["TotalPage"]);
                    pTotalRecord = int.Parse(_json["RecordCount"]);

                    txtStat.Text = "共有" + pTotalRecord + "条记录,第" + pPageIndex.ToString() + "页/共" + pTotalPage + "页," + pPageSize.ToString() + "/每页";
                    txtPageIndex.Text = pPageIndex.ToString();
                    txtStat.Foreground = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));

                }
                catch (Exception ex)
                {

                }

            }
            else
            {

            }
        }

        /// <summary>
        /// 上页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPrev_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            pPageIndex = pPageIndex <= 1 ? 1 : pPageIndex - 1;
            LoadData();
            LoadDataStatistic();
        }

        /// <summary>
        /// 下页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNext_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            pPageIndex = pPageIndex >= pTotalPage ? pTotalPage : pPageIndex + 1;
            LoadData();
            LoadDataStatistic();
        }

        /// <summary>
        /// 首页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFirst_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            pPageIndex = 1;
            LoadData();
            LoadDataStatistic();
        }

        /// <summary>
        /// 末页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLast_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            pPageIndex = pTotalPage;
            LoadData();
            LoadDataStatistic();
        }

        /// <summary>
        /// 跳转到指定页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPageGo_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            LoadPageIndexData();
        }

        private void LoadPageIndexData() 
        {
            int _currentPageIndex = 1;
            if (!int.TryParse(txtPageIndex.Text, out _currentPageIndex))
            {
                txtPageIndex.Text = _currentPageIndex.ToString();
            }

            if (_currentPageIndex >= pTotalPage)
            {
                _currentPageIndex = pTotalPage;
                txtPageIndex.Text = _currentPageIndex.ToString();
            }

            if (_currentPageIndex <= 1)
            {
                _currentPageIndex = 1;
                txtPageIndex.Text = _currentPageIndex.ToString();
            }

            pPageIndex = _currentPageIndex;
            LoadData();
            LoadDataStatistic();
        }

        /// <summary>
        /// 输入页数回车后,查询指定页数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtPageIndex_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Enter) 
            {
                LoadPageIndexData();
            }
        }

    }

    /// <summary>
    /// 返回数据的类
    /// </summary>
    public class Data
    {
        public Guid F_ID { get; set; }
        public string F_ClassName { get; set; }
        public int F_RootId { get; set; }
        public int F_Depth { get; set; }
        public string F_Type { get; set; }
    }  

   
}

 

主要思路:
定义一组变量变于保存查询参数(包括当前第几页,每页多少条记录之类),然后利用WebClient访问wcf,将json数据download回来,成功后解析为json对象,再转化为强类型的List<Data>,最后绑定完事

运行效果图:

时间: 2024-09-20 00:46:37

silverlight + wcf(json格式) + sqlserver存储过程分页的相关文章

sqlserver 存储过程分页代码第1/2页

复制代码 代码如下:declare @TotalCount int declare @TotalPageCount int exec P_viewPage_A 'type1','*','id','','id asc',1,0,4,3,@TotalCount output,@TotalPageCount output select * from type1 Create PROC P_viewPage_A /* nzperfect [no_mIss] 高效通用分页存储过程(双向检索) 2007.5

sqlserver 存储过程分页(按多条件排序)

cs页面调用代码: 复制代码 代码如下: public int TotalPage = 0; public int PageCurrent = 1; public int PageSize = 25; public int RowsCount = 0; string userid, username; public DataTable dt = new DataTable(); public string path, userwelcome; public string opt,cid; pro

sqlserver 存储过程分页(按多条件排序)_MsSql

cs页面调用代码: 复制代码 代码如下: public int TotalPage = 0; public int PageCurrent = 1; public int PageSize = 25; public int RowsCount = 0; string userid, username; public DataTable dt = new DataTable(); public string path, userwelcome; public string opt,cid; pro

分页 SQLServer存储过程

server|sqlserver|存储过程|分页 /*--用存储过程实现的分页程序显示指定表.视图.查询结果的第X页对于表中主键或标识列的情况,直接从原表取数查询,其它情况使用临时表的方法如果视图或查询结果中有主键,不推荐此方法--邹建 2003.09--*//*--调用示例exec p_show '地区资料'exec p_show '地区资料',5,3,'地区编号,地区名称,助记码','地区编号'--*//*因为要顾及通用性,所以对带排序的查询语句有一定要求.如果先排序,再出结果.就是:exe

sqlserver 通用存储过程分页代码

分页存储过程大致有下列几种 1. 利用Not in 和select top 2. 利用id大于多少和select top 3. 利用sql中的游标 4.临时表 可以参看网上的以下链接 C#中常用的分页存储过程小结 http://read.newbooks.com.cn/info/174545.html 在2005中我们的选择就多了,可以利用新语法CTE(公用表表达式),关于CTE的介绍大家可以参看博客园中一位仁兄的系列教程 http://www.cnblogs.com/nokiaguy/arch

Silverlight+WCF 实战-网络象棋最终篇之房间装修-WCF端(二)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 上一系列四十篇索引:Silverlight+WCF 新手实例 象棋 专题索引   佛靠金装,人要衣裳,房间也要加金砖.本篇我们来把房间装修下,让它看起来专业一点!   一:效果预览,先上图   这是之前的房间图片: 今天我们要装修成的房间图片: 再上一张游戏中的效果图:   二:实现说明   1:新增加图片 为了实现装修,我这里新增加了3张图片: 1:房间图片 2:房间游戏中状态的图片 3:QQ用户头像 图片是从QQ象棋游戏

请教GridView利用存储过程分页的问题?谢谢!

问题描述 本人属于菜鸟,跪求GridView利用存储过程分页的代码,最好有详细的说明.使用的后台语言为C#,数据库为SQLServer.不胜感谢! 解决方案 解决方案二: 可以用session也可以用隐藏控件之类的解决方案三: 俄搞错了我还以为是状态保存解决方案四: <asp:LabelID="lblPage"runat="server"Text='<%#"第"+(((GridView)Container.NamingContaine

Extjs怎么将Handler.ashx返回的json格式数据绑定到grid上面?

问题描述 如题,还有分页是怎么实现的?以下为js代码以下为Handler.ashx代码运行就是不显示数据,但是Handler.ashx确实返回了一个json格式的字符串.求帮忙,初学之中 解决方案

求一个sqlserver存储过程

问题描述 求一个sqlserver存储过程 我在后台取到了一个List集合,现在要保存到数据库里,现在求一个存储过程,参数为list集合,然后循环插入list中的数据 解决方案 不接受这类参数,你要么组织成字符串,存储过程解析,或者穿xml格式字符串,也可以,存储过程可以取里面的节点值 解决方案二: 哦哦,难怪我找了好久都没找到,我是一个XML文件里数据拿出来放到数据库里面,但是XML里少了一个字段,我要处理一下,在放到数据库里面,请问有什么解决的办法? 解决方案三: 可以做的,不过需要数据库中