通过分析蜘蛛侠论坛中的版块管理功能来介绍该如何使用我开发出来的ROM框架

简介:

 http://www.cnblogs.com/netfocus/archive/2010/01/10/1643207.html

 上面这个是框架发布页面的地址。

 

就以论坛版块管理模块作为例子来介绍这个框架吧,包括显示版块列表、新增版块、修改版块、删除版块四个功能;

1. 表设计:

复制代码
SQL代码
1  CREATE   TABLE   [ tb_Sections ] (
2       [ EntityId ]   [ int ]   IDENTITY ( 1 , 1 NOT   NULL ,
3       [ Subject ]   [ varchar ] ( 128 NOT   NULL ,
4       [ Enabled ]   [ int ]   NOT   NULL ,
5       [ GroupId ]   [ int ]   NOT   NULL ,
6       [ TotalThreads ]   [ int ]   NOT   NULL
7  ON   [ PRIMARY ]
复制代码

 

2. ROM配置文件:

复制代码
 1  < table  name ="tb_Sections" >
 2       < field  name ="EntityId"  type ="int"  typeEnum ="Int"  size ="4"  isIdentity ="true"   />
 3       < field  name ="Subject"  type ="varchar(128)"  typeEnum ="VarChar"  size ="128"   />
 4       < field  name ="Enabled"  type ="int"  typeEnum ="Int"  size ="1"   />
 5       < field  name ="GroupId"  type ="int"  typeEnum ="Int"  size ="4"   />
 6       < field  name ="TotalThreads"  type ="int"  typeEnum ="Int"  size ="4"   />
 7  </ table >
 8  < entityMapping  entityType ="Forum.Business.Section, Forum.Business"  tableName ="tb_Sections" >
 9       < propertyNode  propertyName ="EntityId"  fieldName ="EntityId"   />
10       < propertyNode  propertyName ="Subject"  fieldName ="Subject"   />
11       < propertyNode  propertyName ="Enabled"  fieldName ="Enabled"   />
12       < propertyNode  propertyName ="GroupId"  fieldName ="GroupId"   />
13       < propertyNode  propertyName ="TotalThreads"  fieldName ="TotalThreads"   />
14  </ entityMapping >
复制代码

说明:table结点表示tb_Sections表的结构;entityMapping结点表示Section对象和tb_Sections表的对应关系;

 

需要特别说明的是,对象可以嵌套并和表或视图的字段对应;例如下面这个例子:

复制代码
 1  < entityMapping  entityType ="System.Web.Core.UserAndRole, System.Web.Core"  tableName ="vw_RoleUsers" >
 2       < propertyNode  propertyName ="EntityId"  fieldName ="EntityId"   />
 3       < propertyNode  propertyName ="User" >
 4           < propertyNode  propertyName ="EntityId"  fieldName ="UserId"   />
 5           < propertyNode  propertyName ="MemberId"  fieldName ="MemberId"   />
 6           < propertyNode  propertyName ="NickName"  fieldName ="NickName"   />
 7           < propertyNode  propertyName ="Email"  fieldName ="Email"   />
 8           < propertyNode  propertyName ="AvatarFileName"  fieldName ="AvatarFileName"   />
 9           < propertyNode  propertyName ="AvatarContent"  fieldName ="AvatarContent"   />
10           < propertyNode  propertyName ="UserStatus"  fieldName ="UserStatus"   />
11           < propertyNode  propertyName ="TotalMarks"  fieldName ="TotalMarks"   />
12       </ propertyNode >
13       < propertyNode  propertyName ="Role" >
14           < propertyNode  propertyName ="EntityId"  fieldName ="RoleId"   />
15           < propertyNode  propertyName ="Name"  fieldName ="RoleName"   />
16           < propertyNode  propertyName ="Description"  fieldName ="RoleDescription"   />
17           < propertyNode  propertyName ="RoleType"  fieldName ="RoleType"   />
18       </ propertyNode >
19  </ entityMapping >
复制代码

 

UserAndRole对象中包含了一个User对象和一个Role对象,UserAndRole对象和一个视图vw_RoleUsers对应;其中User对象中的一些属性和视图中的相关字段对应,Role对象也是一样;

 

3. 功能实现:

3.1 显示版块列表、删除版块功能的实现:

复制代码
  1  public   class  SectionList : ForumUserControl
  2  {
  3       protected  Repeater list;
  4       protected  ValuedDropDownList groupDropDownList;
  5       protected  AjaxPager pager;
  6       protected  CurrentPage currentPage;
  7 
  8       public   string  AdminUserRoleId
  9      {
 10           get
 11          {
 12               string  s  =  ViewState[ " AdminUserRoleId " as   string ;
 13               if  (s  ==   null )
 14              {
 15                  s  =   string .Empty;
 16              }
 17               return  s;
 18          }
 19           set
 20          {
 21              ViewState[ " AdminUserRoleId " =  value;
 22          }
 23      }
 24 
 25       protected   override   void  OnFirstLoad()
 26      {
 27           if  ( ! ValidatePermission(PermissionType.SectionAdmin))
 28          {
 29               throw   new  Exception( " 您没有管理版块或版块组的权限! " );
 30          }
 31      }
 32       public   override   void  GetRequests(List < RequestBinder >  requestBinders)
 33      {
 34          requestBinders.Add(BinderBuilder.BuildGetAllBinder( this new  TRequest < Group > ()));
 35 
 36          TRequest < Section >  request  =   new  TRequest < Section > ();
 37          request.PageSize  =  pager.PageSize;
 38          requestBinders.Add(BinderBuilder.BuildGetListBinder( this , request));
 39      }
 40       public   override   void  GetReplies(List < RequestBinder >  requestBinders)
 41      {
 42          BindGroupDropDownList(requestBinders[ 0 ].Reply.EntityList);
 43          BindRepeater(requestBinders[ 1 ].Reply);
 44          BindPager(requestBinders[ 1 ].Reply.TotalRecords,  1 );
 45      }
 46 
 47       #region  Ajax Methods
 48 
 49      [AjaxMethod]
 50       public   void  DeleteSection( int  sectionId)
 51      {
 52          TRequest < Post >  postRequest  =   new  TRequest < Post > ();
 53          postRequest.Data.SectionId.Value  =  sectionId;
 54 
 55          ThreadRequest threadRequest  =   new  ThreadRequest();
 56          threadRequest.Data.SectionId.Value  =  sectionId;
 57 
 58          TRequest < SectionRoleUser >  sectionRoleUserRequest  =   new  TRequest < SectionRoleUser > ();
 59          sectionRoleUserRequest.Data.SectionId.Value  =  sectionId;
 60 
 61          ProcessResult result  =  Engine.Executes(BinderBuilder.BuildDeleteListBinder(postRequest), BinderBuilder.BuildDeleteListBinder(threadRequest), BinderBuilder.BuildDeleteListBinder(sectionRoleUserRequest), BinderBuilder.BuildDeleteBinder < Section > (sectionId));
 62           if  ( ! result.IsSuccess)
 63          {
 64               throw   new  Exception(result.ErrorMessage);
 65          }
 66      }
 67      [AjaxMethod]
 68       public   void  DeleteSections( string  items)
 69      {
 70           if  ( string .IsNullOrEmpty(items))
 71          {
 72               return ;
 73          }
 74           int  entityId  =   0 ;
 75           foreach  ( string  item  in  items.Split( new   char [] {  ' : '  }, StringSplitOptions.RemoveEmptyEntries))
 76          {
 77              entityId  =  Globals.ChangeType < int > (item);
 78               if  (entityId  >   0 )
 79              {
 80                  DeleteSection(entityId);
 81              }
 82          }
 83      }
 84      [AjaxMethod]
 85       public  ListManageAjaxData RefreshList( int  groupId,  int  pageIndex)
 86      {
 87          TRequest < Section >  request  =   new  TRequest < Section > ();
 88 
 89          request.Data.GroupId.Value  =  groupId;
 90          request.PageIndex  =  pageIndex;
 91          request.PageSize  =  pager.PageSize;
 92 
 93          Reply reply  =  Engine.GetEntityList(request);
 94 
 95          BindRepeater(reply);
 96          BindPager(reply.TotalRecords, pageIndex);
 97 
 98          ListManageAjaxData result  =   new  ListManageAjaxData();
 99          result.ListContent  =  Globals.RenderControl(list);
100          result.PagingContent  =  Globals.RenderControl(currentPage)  +  Globals.RenderControl(pager);
101 
102           return  result;
103      }
104 
105       #endregion
106 
107       #region  Private Methods
108 
109       private   void  BindGroupDropDownList(EntityList groups)
110      {
111          Group topGroup  =   new  Group();
112          topGroup.Subject.Value  =   " 所有版块组 " ;
113          groups.Insert( 0 , topGroup);
114 
115          groupDropDownList.DataSource  =  groups;
116          groupDropDownList.DataTextField  =   " Subject " ;
117          groupDropDownList.DataValueField  =   " EntityId " ;
118          groupDropDownList.DataBind();
119      }
120       private   void  BindRepeater(Reply reply)
121      {
122          AdminUserRoleId  =  RoleManager.GetRole(ForumConfiguration.Instance.ForumSectionAdminRoleName).EntityId.Value.ToString();
123          list.DataSource  =  reply.EntityList;
124          list.DataBind();
125      }
126       private   void  BindPager( int  totalRecords,  int  pageIndex)
127      {
128           if  (pager  !=   null )
129          {
130              pager.TotalRecords  =  totalRecords;
131              pager.PageIndex  =  pageIndex;
132               if  (currentPage  !=   null )
133              {
134                  currentPage.TotalRecords  =  pager.TotalRecords;
135                  currentPage.TotalPages  =  pager.TotalPages;
136                  currentPage.PageIndex  =  pager.PageIndex;
137              }
138          }
139      }
140 
141       #endregion
142  }
复制代码

 

说明:

OnFirstLoad函数在前页面第一次显示时被调用,我在该函数中进行了权限的判断:

复制代码
1  protected   override   void  OnFirstLoad()
2  {
3       if  ( ! ValidatePermission(PermissionType.SectionAdmin))
4      {
5           throw   new  Exception( " 您没有管理版块或版块组的权限! " );
6      }
7  }
复制代码

 

 

在基类控件中规定如下的时候才会调用该方法:

复制代码
1  protected   override   void  OnLoad(EventArgs e)
2  {
3       if  ( ! Page.IsPostBack  &&   ! Page.IsCallback  &&   ! AjaxManager.IsCallBack)
4      {
5          OnFirstLoad();
6      }
7  }
复制代码

 

 

重写GetRequests函数使得各个具体控件有机会告诉框架当前的Url请求需要发送什么数据请求。GetRequests函数由框架负责调用,在这个例子中,创建了两个请求并添加到集合中:

1  requestBinders.Add(BinderBuilder.BuildGetAllBinder( this new  TRequest < Group > ()));
2 
3  TRequest < Section >  request  =   new  TRequest < Section > ();
4  request.PageSize  =  pager.PageSize;
5  requestBinders.Add(BinderBuilder.BuildGetListBinder( this , request));

 

其中第一个请求目的是获取所有的版块分组,第二个请求目的是为了获取当前页下的所有版块信息;BuildGetAllBinder方法告诉框架我不需要分页获取数据,而是获取这类数据的全部记录;

BuildGetListBinder告诉框架应该获取当前PageIndex下的PageSize条记录;

 

另外,我们还重写了GetReplies方法,该方法由框架调用。当框架获取了所请求的数据后,会调用该方法,将请求的回复返回给请求者。在该方法中,我们可以对返回的数据进行处理,如绑定到Repeater控件和设置分页控件信息等。

复制代码
1  public   override   void  GetReplies(List < RequestBinder >  requestBinders)
2  {
3      BindGroupDropDownList(requestBinders[ 0 ].Reply.EntityList);
4      BindRepeater(requestBinders[ 1 ].Reply);
5      BindPager(requestBinders[ 1 ].Reply.TotalRecords,  1 );
6  }
复制代码

 

其中requestBinders[0]表示第一个请求的回复,requestBinders[1]表示第二个请求的回复;BindGroupDropDownList、BinderRepeater、BindPager三个函数分别用来将返回的数据绑定到控件;

 

通过GetRequests、以及GetReplies这两个函数,我们可以不必自己去关心该在什么时候去获取数据,而只要告诉框架我要获取什么数据即可;这样做的好处是,比如当前页面有10个用户控件,每个用户控件都需要获取自己所需要的数据,我们以往的做法是,每个控件自己去建立数据库连接并自己负责去获取数据并处理数据。这样做带来的后果是一次页面显示时,可能需要建立10次数据库连接,这样会影响性能;而如果基于我这样的设计,10个用户控件自己并不负责去建立数据库连接,而只是简单的告诉框架我要获取什么数据,框架会负责搜集搜索当前请求所需要的所有数据库请求,并一次性执行,并且只需要建立一次数据库连接即可。等所有请求处理完之后,再统一将所有的回复发给相应的控件。

 

删除版块功能的实现,通过Ajax技术实现,代码如下:

复制代码
 1  [AjaxMethod]
 2  public   void  DeleteSection( int  sectionId)
 3  {
 4      TRequest < Post >  postRequest  =   new  TRequest < Post > ();
 5      postRequest.Data.SectionId.Value  =  sectionId;
 6 
 7      ThreadRequest threadRequest  =   new  ThreadRequest();
 8      threadRequest.Data.SectionId.Value  =  sectionId;
 9 
10      TRequest < SectionRoleUser >  sectionRoleUserRequest  =   new  TRequest < SectionRoleUser > ();
11      sectionRoleUserRequest.Data.SectionId.Value  =  sectionId;
12 
13      ProcessResult result  =  Engine.Executes(
14          BinderBuilder.BuildDeleteListBinder(postRequest),
15          BinderBuilder.BuildDeleteListBinder(threadRequest),
16          BinderBuilder.BuildDeleteListBinder(sectionRoleUserRequest),
17          BinderBuilder.BuildDeleteBinder < Section > (sectionId));
18 
19       if  ( ! result.IsSuccess)
20      {
21           throw   new  Exception(result.ErrorMessage);
22      }
23  }
复制代码

 

该函数接受一个由Ajax框架传递过来的一个sectionId。首先交代一下一个论坛中一些基本表的关系:一个版块下包含多个帖子,一个帖子包含多个回复,另外一个版块还会有一些版主;

所以当我要删除一个版块时,还必须级联删除所有与之相关的帖子、回复、版主信息;而所有这些删除操作必须以事务的方式来执行,这样才可以确保数据完整性。

所以,上面的函数中我创建了四个请求,并全部传递给数据处理引擎Engine的Executes方法,该方法可以接受多个请求,并以事务的方式执行所有的请求;

BuildDeleteListBinder表示我要创建一个请求,该请求会删除符合指定条件下的所有记录;BuildDeleteBinder表示我要创建一个请求,该请求会根据一个主键删除一个实体,而实体的类型由泛型类型来告诉框架;

 

3.2 新增版块:

为了简单起见,我直接介绍新增版块的相关代码,而不写在前面已经介绍过的代码了。

复制代码
 1  [AjaxMethod(IncludeControlValuesWithCallBack  =   true )]
 2  public   void  Save()
 3  {
 4      CheckData();
 5 
 6      Section section  =   new  Section();
 7      section.Subject.Value  =  subjectTextBox.Value;
 8      section.Enabled.Value  =  enabledCheckBox.Checked  ?   1  :  0 ;
 9      section.GroupId.Value  =   int .Parse(groupDropDownList.Value);
10      Engine.Create(section);
11  }
12 
13  private   void  CheckData()
14  {
15       if  ( string .IsNullOrEmpty(groupDropDownList.Value))
16      {
17           throw   new  Exception( " 请选择一个版块组! " );
18      }
19 
20      TRequest < Section >  request  =   new  TRequest < Section > ();
21      request.Data.Subject.Value  =  subjectTextBox.Value.Trim();
22       if  (Engine.GetAll(request).Count  >   0 )
23      {
24           throw   new  Exception( " 您要添加的版块已经存在! " );
25      }
26  }
复制代码

 

在添加版块时,需要检查名称是否重复,在CheckData函数中,通过调用Engine提供的GetAll方法来获取所有当前版块名称的记录,如果有,说明存在重复;如果不存在,则做保存操作。

可以清晰的看到,我先创建一个版块对象,然后调用Engine.Create方法完成版块的创建。

 

3.3 修改版块:

复制代码
 1  [AjaxMethod(IncludeControlValuesWithCallBack  =   true )]
 2  public   void  Save()
 3  {
 4      Section section  =  Engine.Get < Section > ( new  TRequest < Section > (GetValue < int > (ForumParameterName.SectionId)));
 5 
 6      CheckData(section);
 7 
 8      section.Enabled.Value  =  enabledCheckBox.Checked  ?   1  :  0 ;
 9      section.Subject.Value  =  subjectTextBox.Value;
10      Engine.Update(section);
11  }
12  private   void  CheckData(Section section)
13  {
14       if  (section  ==   null )
15      {
16           throw   new  Exception( " 版块组已经被删除! " );
17      }
18      TRequest < Section >  request  =   new  TRequest < Section > ();
19      request.Data.Subject.Value  =  subjectTextBox.Value.Trim();
20      EntityList sections  =  Engine.GetAll(request);
21       if  (sections.Count  >   0   &&  ((Section)sections[ 0 ]).EntityId.Value  !=  section.EntityId.Value)
22      {
23           throw   new  Exception( " 新版块名称和已有的版块名称重复! " );
24      }
25  }
复制代码

 

在保存修改的版块时,首先通过Engine.Get<TEntity>方法获取当前正在编辑的版块,然后同样先检查版块名称是否合法,如果合法,

则调用Engine.Update方法保存版块;一切看起来都非常简单。

 

总结:

本文通过介绍一个论坛中版块的管理来简单介绍该如何使用我的框架所提供的实用功能。基于我提供的框架,当我们以后要开发一个应用模块时,只要先创建好表,然后做几个非常简单的ROM配置,然后就可以调用框架提供的接口来完成你想要的数据处理请求了。而你的所有数据处理请求都是创建Request,然后发送给框架,然后框架就会返回给你一个Reply,或者直接返回你想要的数据。也就是说,你以后都不必再写SQL了,也不需要写自己的数据访问层了。当然,现在很多ROM框架也都已经提供了非常强大的功能,让我们在开发应用时,可以不必去面向数据库字段,而是直接面向对象的属性。我开发这个ROM框架,也是希望能够提供给大家另外一种ROM的选择。当然我自知自己的这个东西还远不能和Hibernate,EF等大型成熟的框架相提并论,并且我还从未研究过他们的实现,呵呵。我只是希望通过自己的努力和积累,可以让我自己的开发很简单快捷而已。当然因为同时也希望能给大家分享我的成果,才发布给大家,并在这里写文章介绍这个东西。我觉得现在的我是多么的纯洁和可爱啊,应该说还没有被社会污染,哈哈。

 

好了,就这么多吧!这个框架的其他内容,如果大家有兴趣,就自行去研究吧,基本上所有的功能在我发布的蜘蛛侠论坛中都已经用到了。


目录
相关文章
|
8月前
|
安全
dapp公排矩阵互助模式系统开发指南步骤/详细需求/功能设计/源码案例
The development of a public matrix mutual aid crowdfunding model system for DApp (decentralized application) involves the application of blockchain technology and smart contracts. The following are the main steps and requirements for development:
|
8月前
|
存储 供应链 安全
dapp系统开发详细规则/玩法功能/案例设计/源码步骤
DApp是指去中心化应用(Decentralized Application),是构建在区块链技术之上的应用程序。与传统的中心化应用不同,DApp不依赖于中心化的服务器或管理者,而是通过智能合约和分布式网络来实现去中心化的运行。
|
存储 小程序 JavaScript
借助云开发实现小程序的登陆注册功能
借助云开发实现小程序的登陆注册功能
305 0
|
算法 Perl
技术下午茶:产品经理是如何工作的?如何才算一份好的需求文档?如何设计一个简单的列表,它应该具备哪些基本功能?
技术下午茶:产品经理是如何工作的?如何才算一份好的需求文档?如何设计一个简单的列表,它应该具备哪些基本功能?
119 1
|
8月前
|
Ubuntu Linux 开发工具
【专栏】在Linux上,exa是一个现代化的文件管理系统替代工具,提供直观的文件信息展示。
【4月更文挑战第28天】在Linux上,exa是一个现代化的文件管理系统替代工具,提供直观的文件信息展示。要安装exa,可以在基于Debian的系统(如Ubuntu)上运行`sudo apt install exa`,基于RedHat(如CentOS)的系统运行`sudo yum install exa`,或从源代码编译安装。使用exa的基本命令是`exa`,它列出当前目录的文件和目录。通过选项如`-F`(显示文件类型)、`-h`(人类可读大小)、`-l`(详细信息)和`-s`(排序)可以定制输出。exa还能与其他命令(如grep)结合使用,提升效率。
106 0
|
8月前
|
Go
区域代理分红商城系统开发指南教程/步骤功能/方案逻辑/源码项目
The development of regional proxy dividend distribution mall system involves multiple aspects such as proxy dividend function and electronic mall system development. The following is an overview of the steps for developing a regional agent dividend distribution mall system
|
8月前
|
安全 区块链
DAPP商城系统开发详情版/案例设计/需求功能/源码教程
Requirement Analysis * *: Understand customer needs, determine the functions and features of the DApp mall system, including user registration, product display, purchase process, payment function, order management, user evaluation
|
新零售 人工智能 大数据
旅游系统开发(APP开发案例)/功能介绍/案例分析/项目方案/源码平台
新零售是指个人、企业以互联网为依托,通过运用大数据、人工智能等先进技术手段并运用心理学知识,A new retail model that upgrades and transforms the production,circulation,and sales processes of goods,reshapes the business structure and ecosystem,and deeply integrates online services,offline experiences,and modern logistics
|
安全 Go 区块链
区块链游戏链游系统开发功能详情丨方案逻辑丨开发项目丨案例分析丨源码规则
 In recent years, with the continuous development of blockchain technology, NFTs (non homogeneous tokens) and DAPPs (decentralized applications) have emerged in the gaming industry.
|
存储 JSON 安全
旅游APP开发详情丨旅游系统开发案例设计/功能方案/逻辑项目/源码平台
 数据共享和分发:区块链中的链式结构允许数据在网络中被共享和分发。每个参与节点都可以获得完整的区块链副本,从而保持数据的同步和一致性。这种去中心化的特点使得区块链具有高度的可靠性和抗故障能力。

热门文章

最新文章