惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security @ Cisco Blogs
H
Hacker News: Front Page
P
Privacy International News Feed
N
News and Events Feed by Topic
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
K
Kaspersky official blog
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
Jina AI
Jina AI
P
Proofpoint News Feed
AI
AI
雷峰网
雷峰网
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 叶小钗
Webroot Blog
Webroot Blog
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
罗磊的独立博客
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
S
Security Affairs
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
月光博客
月光博客
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Securelist
W
WeLiveSecurity
T
Troy Hunt's Blog
A
Arctic Wolf
博客园 - 司徒正美

博客园 - 大熊(BigBear)

ADO.net实现批量SQL操作. - 大熊(BigBear) - 博客园 Application_AcquireRequestState事件,导致Ajax客户端不能加载 Moss中Form验证中"找不到匹配项"问题的处理 对于知识库系统建设的思考 知识管理中知识地图详解〔转〕 知识管理中的一些概念 Aop面向方面编程之PostSharp框架 [摘]IIS上部署WCF的问题 Linq使用之分组 Silverlight表格绑定中的一点细节处理 页面加载性能的优化 由一棵树绑定引发的遐想 IBatis.Net使用MemCached替换内置缓存策略 .Net下调用Java安全Web服务 Webpart深入(二) Webpart深入(一) ASP.NET MVC 中文文档3 ASP.NET MVC 中文文档2 ASP.net MVC 中文文档1
CSLA.Net在Web项目中使用SQL2005的分页
大熊(BigBear) · 2010-01-28 · via 博客园 - 大熊(BigBear)

正用CSLA.NET做一个Web的项目, 发现CSLA的模型在开发Web时, 不是很适合中国国情.

他的一系列模版, 都是基于主从表单的考虑, 比如"采购单", 这样有单头, 有明细行的情况, 这在WinForm下很棒.

但Web下, 大部分对象都单独用一个表单进行编辑, 所以感觉有些别扭.

我的理解还不深入, 还不断学习中, 整个框架让我受益很多. 废话完了, 进入正题.

要在CSLA模型中方便的使用Sql2005的分页, 我们要做四步.

第一步: 实现一个PagingCriteria, 用来传递分页参数.

    [Serializable()]
    public class PagingCriteria<T> : CriteriaBase
    {
        #region Filed
        public IDictionary ParamDic { get; private set; }
        public string SortExpression { get; private set; }
        public string DefaultOrder { get; private set; }
        public int StartRowIndex { get; private set; }
        public int MaximumRows { get; private set; }
        #endregion

        protected PagingCriteria(){ }

        public PagingCriteria(IDictionary paramDic, int startRowIndex, int maximumRows, string sortExpression, string defaultOrder)
            : base(typeof(T))
        {
            ParamDic = paramDic;
            SortExpression = sortExpression;
            DefaultOrder = defaultOrder;
            StartRowIndex = startRowIndex;
            MaximumRows = maximumRows;
        }
    }

第二步: 实现PagingWrapper, 将普通的Sql语句封装成可分页的语句.

    public static class PagingWrapper
    {
        private const string SQLTEMPLATE = @"With TargetTable AS(select ROW_NUMBER() OVER (order by Temp.{1})as RowNumber,Temp.* from ({0}) as Temp) select * from TargetTable WHERE RowNumber between {2} and {3};Select count(*) from ({0}) Temp";
        public static string Wrap(string sqlQuery, string SortExpression, int startRowIndex, int maximumRows)
        {
            if (string.IsNullOrEmpty(SortExpression))
                throw new Exception("未指定排序列.");

            return string.Format(SQLTEMPLATE, sqlQuery, SortExpression, startRowIndex +1, startRowIndex + maximumRows);
        }

        public static string Wrap<T>(string sqlQuery, PagingCriteria<T> criteria)
        {
            string order = (string.IsNullOrEmpty(criteria.SortExpression)) ? criteria.DefaultOrder : criteria.SortExpression;
            return Wrap(sqlQuery, order, criteria.StartRowIndex, criteria.MaximumRows);
        }
    }

第三部: 在集合对象中调用.这里是RoleList.

using (SqlCommand cm = cn.CreateCommand())
{
    cm.CommandType = CommandType.Text;
    string sql = "SELECT * FROM Roles";
    cm.CommandText = PagingWrapper.Wrap(sql, criteria);
    using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
    {
        while (dr.Read())
        Add(Role.FillRole(dr));
        dr.NextResult();
        dr.Read();
        TotalRowCount = dr.GetInt32(0);
     }
}

CommandText就是调用用Wrapper返回的. TotalRowCount属性是Csla.Core.IReportTotalRowCount接口的实现.

第四步: 在页面上用数据源控件, 绑定Gridview并实现分页:

private int totalCount = 0;
protected void CslaDs_SelectObject(object sender, Csla.Web.SelectObjectArgs e)
{
     BLL.Security.RoleList list = BLL.Security.RoleList.PagingRoleList(null, e.SortExpression, e.StartRowIndex, e.MaximumRows);
     e.BusinessObject = list;
     totalCount = list.TotalRowCount;
}

protected void gvlist_RowDataBound(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.Pager)
     {
        ((Label)e.Row.FindControl("lblTotal")).Text = totalCount.ToString();
     }
}
public static RoleList PagingRoleList(IDictionary paramDic, string SortExpression, int startRowIndex, int maximumRows)
        {
            return DataPortal.Fetch<RoleList>(new PagingCriteria<RoleList>(paramDic, startRowIndex, maximumRows, SortExpression, "ID"));
        }

页面Gridview分页部分:

<PagerTemplate>
   <br />
   <asp:Label ID="lblTotal" runat="server" ></asp:Label><asp:Label ID="lblPage" runat="server" Text='<%# "第" + (((GridView)Container.NamingContainer).PageIndex + 1)  + "页/共" + (((GridView)Container.NamingContainer).PageCount) + "页" %> '></asp:Label>
   <asp:LinkButton ID="lbnFirst" runat="Server" Text="首页" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'
      CommandName="Page" CommandArgument="First"></asp:LinkButton>
   <asp:LinkButton ID="lbnPrev" runat="server" Text="上一页" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'
       CommandName="Page" CommandArgument="Prev"></asp:LinkButton>
   <asp:LinkButton ID="lbnNext" runat="Server" Text="下一页" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != (((GridView)Container.NamingContainer).PageCount - 1) %>'
       CommandName="Page" CommandArgument="Next"></asp:LinkButton>
   <asp:LinkButton ID="lbnLast" runat="Server" Text="尾页" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != (((GridView)Container.NamingContainer).PageCount - 1) %>'
       CommandName="Page" CommandArgument="Last"></asp:LinkButton>
    <br />
</PagerTemplate>

这里要说明的是, 总行数是通过list.TotalRowCount属性来获得的. 所以RoleList 需要实现Csla.Core.IReportTotalRowCount接口.

你可能会问, 为什么不在Gridview,PagerTemplate中直接写入总行数, 其实是因为Gridview并未暴露这个属性,System.Web.UI.DataSourceSelectArguments对象,

在获取数据后, 会将总行数返回给Gridview内部, 但Gridview内部会在私有方法中,构一个局部的PagedDataSourse, 将总行数记录在里面, 外部无法获取, 通过反射也不行.

所以最简单的方式, 就是先记下来, 然后在RowDataBound事件中把它写上去. 如果你要求完美, 可以自己封装一个Gridview加上这个TotalRowCount属性,并暴露出来.

如果有更好的办法, 请告诉我, 不要保留:)