• “PMS-基础权限管理系统”实施某谱OA系统经验总结


    “PMS-基础权限管理系统”介绍

    "PMS-基础权限管理系统"是我一直想做的一个产品,融合多年开发及维护管理系统的经验,参考了很多系统,精心研制而成。

    可以做为毕业设计参考,新手学习或基础开发平台,适合大中型系统开发,内置功能强大的数据访问组件,独立的缓存,日志,配置管理及邮件发送等企业开发方案。

    2013.07.05

    主要使用的技术和工具:

    MVC3

    jquery

    jquery easyui

    SQL Server 2005+

    方案架构图

    2013.07.10

    OA系统项目结构截图及说明:

    clip_image001

    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.EnumSysMgmtSex.cs

    使用方法

    clip_image002

    clip_image003

    如果要在列表起始位置增加全部,使用

    EnumHelper.GetEnumList(typeof(RiskLevel) ,AppendType.All);

    如果要在列表起始位置增加请选择,使用EnumHelper.GetEnumList(typeof(RiskLevel),AppendType.Select);

    如果要在列表起始位置增加自定义项,使用EnumHelper.GetEnumList(typeof(RiskLevel),"key","value");

    详细实现请详读框架源代码FrameworkEnumUtilEnumHelper.cs

    2. 什么时候使用KeyValuePair

    如果子项目不稳定,变化相对较多(比如过一段时间要增加几个子项目)应该使用KeyValuePair配置,比如国籍

    参见:ABS.OPMS.ConfigurationConfigsKeyValuePair.xml

    使用方法

    clip_image004

    如果要在列表起始位置增加全部,使用ConfigManager.GetKeyValuePair("CompanyNature",AppendType.All);

    如果要在列表起始位置增加请选择,使用ConfigManager.GetKeyValuePair("CompanyNature",AppendType.Select);

    如果要在列表起始位置增加自定义项,使用ConfigManager.GetKeyValuePair("CompanyNature","key","value");

    ConfigManager.GetKeyValuePair方法说明:从配置文件ConfigsKeyValuePair*.xml读取KeyValuePair,为了防止在源代码管理器中多人编辑冲突,可以按模块或其它方式分多个文件,

    比如KeyValuePair.xml,KeyValuePair_SysMgmt.xml等,文件名必须以KeyValuePair开头,以.xml结尾

    详细实现请详读框架源代码FrameworkConfigConfigManager.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的实现,以了解其用法。

  • 相关阅读:
    MATLAB函数大全 .
    让隐藏的virtualBox菜单重新显示
    【转载】matlab 脚本文件和函数文件
    Ubuntu下用命令行快速打开各类型文件
    关于存货的成本计价方式
    C# .net asp学习笔记
    在DLL中怎么共用一个全局变量
    如果比较表中同类型多列值是否相等?
    统计报表(用ROLLUP 汇总数据)
    UML建模
  • 原文地址:https://www.cnblogs.com/fuhongwei041/p/3886462.html
Copyright © 2020-2023  润新知