通过分析蜘蛛侠论坛中的版块管理功能来介绍该如何使用我开发出来的ROM框架
http://www.cnblogs.com/netfocus/archive/2010/01/10/1643207.html
上面这个是框架发布页面的地址。
就以论坛版块管理模块作为例子来介绍这个框架吧,包括显示版块列表、新增版块、修改版块、删除版块四个功能;
1. 表设计:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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]
![复制代码](http://common.cnblogs.com/images/copycode.gif)
2. ROM配置文件:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
说明:table结点表示tb_Sections表的结构;entityMapping结点表示Section对象和tb_Sections表的对应关系;
需要特别说明的是,对象可以嵌套并和表或视图的字段对应;例如下面这个例子:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
UserAndRole对象中包含了一个User对象和一个Role对象,UserAndRole对象和一个视图vw_RoleUsers对应;其中User对象中的一些属性和视图中的相关字段对应,Role对象也是一样;
3. 功能实现:
3.1 显示版块列表、删除版块功能的实现:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
说明:
OnFirstLoad函数在前页面第一次显示时被调用,我在该函数中进行了权限的判断:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
2 {
3 if (!ValidatePermission(PermissionType.SectionAdmin))
4 {
5 throw new Exception("您没有管理版块或版块组的权限!");
6 }
7 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
在基类控件中规定如下的时候才会调用该方法:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
2 {
3 if (!Page.IsPostBack !Page.IsCallback !AjaxManager.IsCallBack)
4 {
5 OnFirstLoad();
6 }
7 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
重写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控件和设置分页控件信息等。
![复制代码](http://common.cnblogs.com/images/copycode.gif)
2 {
3 BindGroupDropDownList(requestBinders[0].Reply.EntityList);
4 BindRepeater(requestBinders[1].Reply);
5 BindPager(requestBinders[1].Reply.TotalRecords, 1);
6 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
其中requestBinders[0]表示第一个请求的回复,requestBinders[1]表示第二个请求的回复;BindGroupDropDownList、BinderRepeater、BindPager三个函数分别用来将返回的数据绑定到控件;
通过GetRequests、以及GetReplies这两个函数,我们可以不必自己去关心该在什么时候去获取数据,而只要告诉框架我要获取什么数据即可;这样做的好处是,比如当前页面有10个用户控件,每个用户控件都需要获取自己所需要的数据,我们以往的做法是,每个控件自己去建立数据库连接并自己负责去获取数据并处理数据。这样做带来的后果是一次页面显示时,可能需要建立10次数据库连接,这样会影响性能;而如果基于我这样的设计,10个用户控件自己并不负责去建立数据库连接,而只是简单的告诉框架我要获取什么数据,框架会负责搜集搜索当前请求所需要的所有数据库请求,并一次性执行,并且只需要建立一次数据库连接即可。等所有请求处理完之后,再统一将所有的回复发给相应的控件。
删除版块功能的实现,通过Ajax技术实现,代码如下:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
该函数接受一个由Ajax框架传递过来的一个sectionId。首先交代一下一个论坛中一些基本表的关系:一个版块下包含多个帖子,一个帖子包含多个回复,另外一个版块还会有一些版主;
所以当我要删除一个版块时,还必须级联删除所有与之相关的帖子、回复、版主信息;而所有这些删除操作必须以事务的方式来执行,这样才可以确保数据完整性。
所以,上面的函数中我创建了四个请求,并全部传递给数据处理引擎Engine的Executes方法,该方法可以接受多个请求,并以事务的方式执行所有的请求;
BuildDeleteListBinder表示我要创建一个请求,该请求会删除符合指定条件下的所有记录;BuildDeleteBinder表示我要创建一个请求,该请求会根据一个主键删除一个实体,而实体的类型由泛型类型来告诉框架;
3.2 新增版块:
为了简单起见,我直接介绍新增版块的相关代码,而不写在前面已经介绍过的代码了。
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
在添加版块时,需要检查名称是否重复,在CheckData函数中,通过调用Engine提供的GetAll方法来获取所有当前版块名称的记录,如果有,说明存在重复;如果不存在,则做保存操作。
可以清晰的看到,我先创建一个版块对象,然后调用Engine.Create方法完成版块的创建。
3.3 修改版块:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
在保存修改的版块时,首先通过Engine.Get TEntity 方法获取当前正在编辑的版块,然后同样先检查版块名称是否合法,如果合法,
则调用Engine.Update方法保存版块;一切看起来都非常简单。
总结:
本文通过介绍一个论坛中版块的管理来简单介绍该如何使用我的框架所提供的实用功能。基于我提供的框架,当我们以后要开发一个应用模块时,只要先创建好表,然后做几个非常简单的ROM配置,然后就可以调用框架提供的接口来完成你想要的数据处理请求了。而你的所有数据处理请求都是创建Request,然后发送给框架,然后框架就会返回给你一个Reply,或者直接返回你想要的数据。也就是说,你以后都不必再写SQL了,也不需要写自己的数据访问层了。当然,现在很多ROM框架也都已经提供了非常强大的功能,让我们在开发应用时,可以不必去面向数据库字段,而是直接面向对象的属性。我开发这个ROM框架,也是希望能够提供给大家另外一种ROM的选择。当然我自知自己的这个东西还远不能和Hibernate,EF等大型成熟的框架相提并论,并且我还从未研究过他们的实现,呵呵。我只是希望通过自己的努力和积累,可以让我自己的开发很简单快捷而已。当然因为同时也希望能给大家分享我的成果,才发布给大家,并在这里写文章介绍这个东西。我觉得现在的我是多么的纯洁和可爱啊,应该说还没有被社会污染,哈哈。
好了,就这么多吧!这个框架的其他内容,如果大家有兴趣,就自行去研究吧,基本上所有的功能在我发布的蜘蛛侠论坛中都已经用到了。
如何建立你的阅读管理系统?以 FlowUs 和 Notion 等笔记软件为例 在《FlowUs 生态:如何建立你的书籍管理系统?》中,我事实上主要介绍了导入书籍信息的几种路径。今天,在这篇文章的基础上,我将继续介绍如何使用 Notion 类工具建立阅读管理系统。 注释:本文方法对于 FlowUs 、Notion 等笔记软件均通用。本文以 FlowUs 为例。
HaaS UI小程序解决方案基础教学|阿里云产品内容精选(三十五) 本文内容取自HaaS技术圈。HaaS(Hardware as a Service)物联网设备云端一体开发框架,整合阿里云、达摩院、平头哥技术,基于数亿物联网设备接入经验,提供积木式硬件开发能力,实现低代码快速开发,帮助中小开发者聚焦业务,实现设备安全上云,加速设备创新迭代。
开放下载!基于PAI个性化推荐系统开发指南 阿里巴巴技术专家傲海从推荐算法开始,到系统工程问题讲解,手把手教你搭建简单智能推荐系统。更有超全文档助力零基础学开发~
社交系统ThinkSNS+安装部署演示 ThinkSNS+版本发布之后,很多小伙伴们反馈安装部署有些困难,那么今天我们就通过录制视频的形式,给大家演示安装部署的全过程,由于时间紧张没有字幕,敬请谅解,后续我们有时间的时候会进行后期处理。
netfocus 对DDD领域驱动设计感兴趣,在.NET/JAVA平台都有多年工作经验。架构方面专注于CQRS/Event Souring/EDA架构的研究和框架开发。热衷于开源,拥有两个个人开源项目:ENode,EQueue
相关文章
- 【华为云技术分享】华为云ServiceStage-企业级微服务开发框架利器
- EF实体框架之CodeFirst八
- 大数据开发keras框架环境配置小结
- 最全三大框架整合(使用映射)——Emp.hbm.xml
- JDK7并行计算框架介绍二 Fork/Join开发实例
- PHP做Web开发的MVC框架(Smarty使用说明 )
- 发现一个nginx LUA开发Web App的框架
- 【HIBERNATE框架开发之六】HIBERNATE中ANNOTATION的关系映射&&组件映射!
- EasyPlayerPro(Windows)流媒体播放器开发之框架讲解
- Weex 框架中 JS Framework 的结构
- 利用Attribute简化Unity框架IOC注入
- Android项目快速开发框架探索(Mysql + OrmLite + Hessian + Sqlite)
- ASP.NET Core 6框架揭秘实例演示[25]:配置与承载环境的应用
- 【项目实战】一文说完日志开发框架汇总介绍
- 关于对FLASH开发,starling、starling feathers、starling MVC框架的理解
- J2EE开发框架搭建(1) - maven搭建多项目
- 使用ThinkPHP框架高速开发站点(多图)
- electron利用nodejs+移动端技术跨平台桌面应用开发框架——记录下,类似node webkit!
- 基于JAVA实现的WEB端UI自动化 - WebDriver框架篇 - 框架设计小结
- 从零开始,学会Python爬虫不再难!!! -- (14)Scrapy框架丨蓄力计划