I am using CSLA.NET to work on a Web project and found that the CSLA model is not very suitable for China's national conditions when developing the Web.
His series of templates are all based on the consideration of master-detail forms, such as "Purchase Order", which has a single header and detail rows, which is great under WinForm.
But under the Web, most objects are edited using a separate form, so it feels a bit awkward.
My understanding is not deep yet, and I am still learning. The whole framework has benefited me a lot. Enough nonsense, let’s get to the point.
To conveniently use Sql2005 paging in the CSLA model, we need to do four steps.
Step 1: Implement a PagingCriteria to pass paging parameters.
[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
protectedPagingCriteria(){ }
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;
}
}
Step 2: Implement PagingWrapper to encapsulate ordinary Sql statements into paging statements.
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("No sorting column specified.");
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);
}
}
Part 3: Called in the collection object. Here is 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 is returned by calling Wrapper. The TotalRowCount property is the implementation of the Csla.Core.IReportTotalRowCount interface.
Step 4: Use data source control on the page, bind Gridview and implement paging:
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"));
}Page Gridview pagination part:
<PagerTemplate>
<br />
Total <asp:Label ID="lblTotal" runat="server" ></asp:Label> rows
<asp:Label ID="lblPage" runat="server" Text='<%# "Page" + (((GridView)Container.NamingContainer).PageIndex + 1) + "Pages/Total" + (((GridView) Container.NamingContainer).PageCount) + "page" %> '></asp:Label>
<asp:LinkButton ID="lbnFirst" runat="Server" Text="Home" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'
CommandName="Page" CommandArgument="First"></asp:LinkButton>
<asp:LinkButton ID="lbnPrev" runat="server" Text="Previous Page" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != 0 %>'
CommandName="Page" CommandArgument="Prev"></asp:LinkButton>
<asp:LinkButton ID="lbnNext" runat="Server" Text="Next Page" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != (((GridView)Container.NamingContainer).PageCount - 1) %>'
CommandName="Page" CommandArgument="Next"></asp:LinkButton>
<asp:LinkButton ID="lbnLast" runat="Server" Text="Last page" Enabled='<%# ((GridView)Container.NamingContainer).PageIndex != (((GridView)Container.NamingContainer).PageCount - 1) %>'
CommandName="Page" CommandArgument="Last"></asp:LinkButton>
<br />
</PagerTemplate> What should be explained here is that the total number of rows is obtained through the list.TotalRowCount property. Therefore, RoleList needs to implement the Csla.Core.IReportTotalRowCount interface.
You may ask, why not write the total number of rows directly in Gridview and PagerTemplate? In fact, it is because Gridview does not expose this property, System.Web.UI.DataSourceSelectArguments object.
After obtaining the data, the total number of rows will be returned to the inside of the Gridview, but the Gridview will construct a local PagedDataSourse in a private method and record the total number of rows in it. It cannot be obtained externally, nor through reflection.
So the simplest way is to write it down first, and then write it in the RowDataBound event. If you require perfection, you can encapsulate a Gridview yourself and add the TotalRowCount property, and expose it.