“PMS-基础权限管理系统”实施某谱OA系统经验总结
“PMS-基础权限管理系统”介绍
"PMS-基础权限管理系统"是我一直想做的一个产品,融合多年开发及维护管理系统的经验,参考了很多系统,精心研制而成。
可以做为毕业设计参考,新手学习或基础开发平台,适合大中型系统开发,内置功能强大的数据访问组件,独立的缓存,日志,配置管理及邮件发送等企业开发方案。
2013.07.05
主要使用的技术和工具:
MVC3
jquery
jquery easyui
SQL Server 2005+
方案架构图
2013.07.10
OA系统项目结构截图及说明:
Abs.Framework::基础类库,包括数据访问(支持多种数据库),邮件发送,缓存,异常处理,日志及常用帮助类。
XX.OPMS.BizProcess:业务逻辑层,主要调用数据访问层完成数据持久化及逻辑运算。
XX.OPMS.Configuration: 配置层,主要存放项目中的SQL脚本配置文件,邮件模板及Key-Value配置。
XX.OPMS.DataAccess:数据访问层,使用基础类库封装的数据访问方法与数据库交互。
XX.OPMS.Enum:枚举层,项目中使用到的枚举统一放在这里,以方便管理。
XX.OPMS.Entity:模型层,项目中创建到的业务模型统一放在这里,以方便管理。
XX.OPMS.Jobs:定时作业,项目中需要定时处理业务数据的任务。
XX.OPMS.WebUI:表现层,项目的界面实现。
2013.07.13
如何使用Enum,KeyValuePair及其适用的场景
1. 什么时候使用Enum
如果子项目稳定,不经常变化(相对较少),并且一般会参与逻辑运算(比如根据用户类别做不同的权限限制)应该使用Enum,比如用户性别
参见:XX.OPMS.Enum\SysMgmt\Sex.cs
使用方法
如果要在列表起始位置增加全部,使用
EnumHelper.GetEnumList(typeof(RiskLevel) ,AppendType.All);
如果要在列表起始位置增加请选择,使用EnumHelper.GetEnumList(typeof(RiskLevel),AppendType.Select);
如果要在列表起始位置增加自定义项,使用EnumHelper.GetEnumList(typeof(RiskLevel),"key","value");
详细实现请详读框架源代码Framework\EnumUtil\EnumHelper.cs
2. 什么时候使用KeyValuePair
如果子项目不稳定,变化相对较多(比如过一段时间要增加几个子项目)应该使用KeyValuePair配置,比如国籍
参见:ABS.OPMS.Configuration\Configs\KeyValuePair.xml
使用方法
如果要在列表起始位置增加全部,使用ConfigManager.GetKeyValuePair("CompanyNature",AppendType.All);
如果要在列表起始位置增加请选择,使用ConfigManager.GetKeyValuePair("CompanyNature",AppendType.Select);
如果要在列表起始位置增加自定义项,使用ConfigManager.GetKeyValuePair("CompanyNature","key","value");
ConfigManager.GetKeyValuePair方法说明:从配置文件Configs\KeyValuePair*.xml读取KeyValuePair,为了防止在源代码管理器中多人编辑冲突,可以按模块或其它方式分多个文件,
比如KeyValuePair.xml,KeyValuePair_SysMgmt.xml等,文件名必须以KeyValuePair开头,以.xml结尾
详细实现请详读框架源代码Framework\Config\ConfigManager.cs
2013.07.17
如何使用动态查询
1.带服务器端分页的动态查询
以商品查询为例:
1.1定义sql模板,其中#StrWhere#是点位符,在程序中动态添加条件后会生成where语句替换掉此点位符
<dataCommand name="Product.Query" database="AuthMgmt">
<commandText>
SELECT @TotalCount=COUNT(1) FROM [dbo].[Product] WITH(NOLOCK)
#StrWhere#
;WITH CTE_Paging
AS
(
SELECT [SysNo]
,[ProductID]
,ROW_NUMBER() OVER(#OrderBy#) AS RowID
FROM [dbo].[Product] WITH(NOLOCK)
#StrWhere#
)
SELECT [SysNo]
,[ProductID]
FROM CTE_Paging
WHERE RowID BETWEEN @StartRowID and @EndRowID
</commandText>
<orderFields>
<field name="SysNo" />
</orderFields>
</dataCommand>
1.2 根据需求定义查询条件,由于需要分页,因此要继承自PagingQuery,一般需要将值类型查询条件设置成可空类型,因为一般业务需求是条件值为空就不参于查询,因此如果值为空就不会添加这个条件。
public class ProductQuery : PagingQuery
{
public int? SysNo { get; set; }
public string Keywords { get; set; }
public int? MfSysNo { get; set; }
public int? CatalogSysNo { get; set; }
}
1.3在程序中动态添加各查询条件,由于需要分页,因此需要使用PagingSqlConditionBuilder
public QueryResult<Product> Query(ProductQuery q)
{
DataCommand cmd = DataCommandManager.GetDataCommand("Product.Query");
string defaultOrderBy = "SysNo DESC";
PagingSqlConditionBuilder sb = new PagingSqlConditionBuilder(cmd, q, defaultOrderBy);
sb.AddCondition(SqlRelation.AND, "SysNo", SqlOperator.Equal, "@SysNo", DbType.Int32, q.SysNo);
sb.AddCondition(SqlRelation.AND, "MfSysNo", SqlOperator.Equal, "@MfSysNo", DbType.Int32, q.MfSysNo);
if (q.CatalogSysNo > 0)
{
sb.AddCondition(SqlRelation.AND, "CatalogSysNo", SqlOperator.Equal, "@CatalogSysNo", DbType.Int32, q.CatalogSysNo);
}
if (!StringHelper.IsNullOrEmpty(q.Keywords))
{
sb.AddLeftBracketCondition(SqlRelation.AND);
sb.AddCondition(SqlRelation.OR, "ProductName", SqlOperator.Like, "@ProductName", DbType.String, q.Keywords);
sb.AddCondition(SqlRelation.OR, "ProductID", SqlOperator.Like, "@ProductID", DbType.String, q.Keywords);
sb.AddCondition(SqlRelation.OR, "Keywords", SqlOperator.Like, "@Keywords", DbType.String, q.Keywords);
sb.AddRightBracketCondition(SqlRelation.AND);
}
sb.BuildSql();
var result = new QueryResult<Product>();
result.rows = cmd.ExecuteEntityList<Product>();
result.total = sb.GetTotalCount();
return result;
}
语句sb.BuildSql();会将上面添加的查询条件生成where语句,然后替换点位符#StrWhere#
具体实现请参考框架源代码
2.不需要服务器端分页的动态查询
2.1定义sql查询
<!--获取所有菜单数据-->
<dataCommand name="SysMenu.Query" database="AuthMgmt">
<commandText>
SELECT [SysNo]
,[MenuType]
,[MenuName]
,[Description]
,[Key]
,[Url]
,[IsShow]
,[DisplayOrder]
,[ParentSysNo]
,Icon
FROM [dbo].[SysMenu]
#StrWhere#
ORDER BY [ParentSysNo],[DisplayOrder]
</commandText>
</dataCommand>
2.2根据需求定义查询条件,不需要分页,就不需要继承自PagingQuery
public class SysMenuQuery
{
public string MenuType { get; set; }
public string MenuName { get; set; }
public string IsShow { get; set; }
public int? ParentSysNo { get; set; }
}
2.3在程序中动态添加各查询条件,不需要分页就直接使用SqlConditionBuilder
public List<SysMenu> Query(SysMenuQuery q)
{
DataCommand cmd = DataCommandManager.GetDataCommand("SysMenu.Query");
SqlConditionBuilder sb = new SqlConditionBuilder(cmd);
sb.AddCondition(SqlRelation.AND, "ParentSysNo", SqlOperator.Equal, "@ParentSysNo", DbType.Int32, q.ParentSysNo);
sb.BuildSql();
return cmd.ExecuteEntityList<SysMenu>();
}
3. 可以查看下PagingSqlConditionBuilder以及SqlConditionBuilder的实现,以了解其用法。
“PMS-基础权限管理系统”实施某谱OA系统经验总结的更多相关文章
- OA系统权限管理设计(转载)
不论什么系统都离不开权限的管理,有一个好的权限管理模块,不仅使我们的系统操作自如,管理方便,也为系统加入亮点. l 不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是 ...
- OA系统权限管理设计方案【转】
l 不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是最基本的功能. l 可以对“组”进行权限分配.对于一个大企业的业务系统来说,如果要求管理员为其下员工逐一分配系统操作权限的话,是 ...
- OA系统权限管理设计方案
(转)OA系统权限管理设计方案 OA系统权限管理设计方案 不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是最基本的功能. 可以对“组”进行权限分配.对于一个大企业的 ...
- 以WCF安全认证方式调用通用权限管理系统获取基础信息资料
在B/S开发中,涉及到获取系统基础资料的问题,因为是在不同平台下的开发,采用了WCF方式获取. 下面是一个调用通用权限管理系统(吉日嘎拉)基础信息资料的一个demo供参考 调用原理图: web.con ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 第一点,上一篇文章中我们讲到codefirst中一些问题包括如图,codefirst在每次执行命令的时候会生成新的 ...
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十四节--后台工作者HangFire与ABP框架Abp.Hangfire及扩展
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于 ...
- OA系统从选型到实施完整攻略
本文结合一线IT人士分享OA实施经验,单纯地讲述OA的选型与实施,为相关经验较少的IT人士提供真正的帮助. 一.如何选择OA系统 说起OA选型,稳定性.易用性.灵活性.成本和服务少不了.但是,只了解这 ...
- .NET Core/.NET5/.NET6 开源项目汇总5:权限管理系统项目
系列目录 [已更新最新开发文章,点击查看详细] 企业管理系统一般包含后台管理UI.组织机构管理.权限管理.日志.数据访问.表单.工作流等常用必备功能.下面收集的几款优秀开源的管理系统,值得大家 ...
- Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
随机推荐
- R语言学习笔记:分析学生的考试成绩
孩子上初中时拿到过全年级一次考试所有科目的考试成绩表,正好可以用于R语言的统计分析学习.为了不泄漏孩子的姓名,就用学号代替了,感兴趣可以下载测试数据进行练习. num class chn math e ...
- iOS设计模式之备忘录模式
备忘录模式 基本理解 这个模式有三个关键角色:原发器(Originator).备忘录(Memento).看管人(caretaker).三者的基本关系是:原发器创建一个包含其状态的备忘录,并传给看管人. ...
- iOSQuartz2D-02-绘制炫酷的下载进度条
效果图 实现思路 要实现绘图,通常需要自定义一个UIView的子类,重写父类的- (void)drawRect:(CGRect)rect方法,在该方法中实现绘图操作 若想显示下载进度,只需要实例化自定 ...
- IOS之UI -- UITableView -- 1 -- 相关初识
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 无法将匿名方法转换为System.Delegate
在WinForm中,不允许非UI线程访问UI,如果非UI线程需要跨线程调用UI控件,通常的解决办法是使用Control类中的Invoke方法,传递给该方法一个委托和委托调用的参数列表(params [ ...
- (转载)APP测试点总结
以下所有测试最后必须在真机上完整的执行1.安装.卸载测试 在真机上的以及通过91等第三方的安装与卸载 安装在手机上还是sd卡上 2.启动app测试3.升级测试 数字签名.升级覆盖安装.下载后手动覆盖安 ...
- 文件输入流 FileInputStream类 文件输出流FileOutputStream ---转载
转载自---http://blog.csdn.net/hguisu/article/details/7418161 111:文件输入流: FileInputStream可以使用read()方法一次读入 ...
- 入门 ARM 汇编(一)—— 知识铺垫
我读着史铁生的散文,零碎的牵扯起我生命中不曾出现过的记忆,一如北方的黄山厚土之中悠忽而来的忧伤的信天游,那些灿若信仰一样的阳光以及阳光下虔诚的子民.我想有一次远行,于细碎流淌的时光与路途之中,观察所有 ...
- gdb 远程调试 android native 程序
ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 先看一张原理图: 我是 Linux 和 Android 双料 0 基础,目前对 gdb 了解的很浅显.(注意 ...
- Linux下Mysql安装
1.下载安装包 首先查看Linux版本: [root@localhost ~]# lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-noarch ...