【分享】一个通用强大的主数据管理系统(架构设计讲解及源码下载)

  这篇文章要讲主数据管理系统(Master Data Management System),是本人创业的其中一个项目,用于管理公司的内部所有系统、系统用户、系统角色、系统权限、服务器管理、系统日志等数据。项目开发只用了1个多月时间,全部由一个人完成的,目前只是个初版本,只满足了初期的需求,如果没时间看下面的架构设计,可以直接下载源码。

 

点击下载源码

 

在线demo:  http://mdms.kudystudio.com/

用户/密码:test1/test1     test2/test2     (注:同一用户在另一浏览器登录,另一用户在session失效后会被逼下线)

 

不少朋友下载源码后不怎么知道运行,请看这里补充的说明:

项目使用vs2010打开,数据使用sql server2005/2008


一、数据库创建与初始化数据

新建名为 Db_MDMS 的数据库

然后按顺序执行目录 Documents\MDMS.Documents\DB 1.0\Scripts 里的sql

1_tables.sql
2_functions.sql
3_stored-procedures.sql
4_init_data.sql


二、修改数据库连接信息
在目录 build\MSH 里修改 MSH.exe.config 的配置节点 MDMS.Db_ConnectionString 的值

三、
在vs2010中运行Web项目 MDMS.Web 或右键选择 default.aspx 页面点击在浏览器中浏览,然后打开目录 build\MSH ,双击MSH.exe运行之


这时,你可以用默认用户/密码 admin/admin888 登录系统了

 

  主数据管理问题存在的根源
  对于大多数的企业都存在主数据管理的问题,个人以为这是由于业务发展的渐进性以及IT技术发展的渐进性造成的,正是由于这种渐进性,各大企业的业务系统从经历了从无到有,从简单到复杂,从而形成了一个又一个的业务竖井。从根本上来说,不可能只使用一个业务系统就能覆盖企业的所有业务,即便对一些国际大型的公司提供的套件来说也是一个不可能完成的任务(即便对套件来说,经常也存在一个跨国企业在不同的国家或地区部署多个实例的现象,也就是没有集中部署该套件,而是在很多地方分散部署了该套件)。对企业来说,业务系统的构建更多是以项目为中心,从下而上的构建系统,而不是至上而下的构建系统——这必然缺乏整个企业范围内的统一规划,从而使得一些需要在各个业务中共享的数据(主数据)被分散到了各个业务系统进行分别管理。由于分散管理的主数据不具备一致性、准确性、完整性,使得各个企业普遍存在着产品管理不力、供应商管理不力、订单管理不力等现象。解决这一问题的根本方法就是引入主数据管理(MDM),主数据不光指需要共享的数据,更包含需要共享的业务规则和策略。

一、主要功能需求

  1.公司内部系统的管理,包括管理系统信息、系统权限定义、系统角色、系统角色拥有的权限等等。

  2.统一的用户管理,包括管理用户信息、登录系统的限制、个人在各个系统的角色、个人在各个系统的永久与临时权限等等。

  3.各系统的日志记录与查看。

  4.服务器的管理。(说明一下,这里只是管理服务器的信息,数据是提供给一个专门管理服务器远程登录的子系统的)

   ...其它扩展需求(多语言目前不需要,但MTV框架已实现了)

 

二、主要界面展示

1.主界面

 2.用户列表

3.个人登录限制

4.个人角色管理

5.个人永久权限

6.个人临时权限

7.系统列表

 8.系统权限定义列表

 9.添加权限项

 10.系统角色管理

 11.系统角色的权限

12.服务器管理

13.系统日志

 

三、数据表设计

LoginLimit : 用户在各个系统的登录限制

LoginState : 用户在各个系统的登录情况

OperationLog : 用户在各个系统的操作日志

PermissionGroup : 系统的权限定义分组

PermissionItem : 系统权限分组里的项

Role : 系统角色信息

Server : 服务器(组)信息

ServerParameter : 服务器参数信息

System : 系统信息

User :用户信息

UserPermission : 用户在各个系统的永久权限

UserRoleMapping : 用户在各个系统的角色关系

UserTempPermission : 用户在各个系统的临时权限

详细设计内容太多,请下载源码看里面的数据库设计文档。

 

三、系统架构说明

 

整个解决方案共20个项目,其中ProviderModules目录下的13个项目是应用WCF服务向业务层提供数据接口,这么做了为了以后把数据接口和网站开发分开来给团队独立管理维护。系统应用了N-tier架构的基本设计模式+WCF服务+MTV框架。其中WCF服务采用了KudySharp里的ModuleFramework,MTV框架也是集成在KudySharp里面的。下面对各个项目作简单的解说。

 

ModuleFramework相关文章(MTV框架还没有时间相关的文章):

KudySharp 中的 ModuleFramework(WCF模块框架) 介绍

 基于KudySharp 中的 ModuleFramework(模块框架)的ModuleServiceHosting(MSH)模块服务托管程序介绍与开发实例

 

 

MDMS.Core项目是核心库,IProvider下是数据操作接口的定义,Models下是数据表实体模型类和其它扩展模型类,Modules下是应用ModuleFramework的相关类。DataProviderFactory用于根据配置产生实现数据接口的实例,而DataProviderManager则是管理这些实例的,下面请看代码:

(原先设计是把Data、IProvider、Models分别放在独立项目的,经典多层项目都这么干,但为了减少项目数,本人都放在MDMS.Core项目中了)

DataProviderFactory
    ///<summary>
///
///</summary>
internal static class DataProviderFactory
{
///<summary>
///
///</summary>
///<typeparam name="TProvider"></typeparam>
///<returns></returns>
public static TProvider Create<TProvider>()
{
TProvider provider;
Type interfaceType = typeof(TProvider);
string interfaceName = interfaceType.FullName;
string providerTypeName = string.Concat(MSHConfigs.MDMS_Db_Provider, ".", interfaceType.Name.Substring(1));

try
{
object instance = Assembly.Load(MSHConfigs.MDMS_Db_Provider).CreateInstance(providerTypeName);

provider = (TProvider)instance;
}
catch (Exception ex)
{
throw new Exception("Fail to create provider instance of " + providerTypeName, ex);
}

return provider;
}
}

 

DataProviderManager
    ///<summary>
///
///</summary>
public static class DataProviderManager
{
private static readonly ReadFreeCache<string, object> providerCache = ReadFreeCache<string, object>.Create(StringComparer.OrdinalIgnoreCase);

///<summary>
///
///</summary>
///<typeparam name="TIProvider"></typeparam>
///<returns></returns>
public static TProvider Get<TProvider>()
{
string interfaceName = typeof(TProvider).FullName;

object provider = providerCache.Get(interfaceName, key => DataProviderFactory.Create<TProvider>());

return (TProvider)provider;
}
}

 

 MDMS.SqlServerProvider项目是数据接口sql server实现类库。里面用了KudySharp里的SqlServerHelper助手类,使数据操作更加简洁,请看下面的基类和用户表的数据接口实现类:

ProviderBase
    ///<summary>
/// 数据提供者基类
///</summary>
public abstract class ProviderBase
{
protected virtual string ConnectionString
{
get
{
return MSHConfigs.MDMS_Db_ConnectionString;
}
}

protected virtual object ExecuteNonQueryWithReturnValueParameter(string spName, params object[] parameterValues)
{
// 自动获取存储过程参数(第二次后会取被缓存的一个拷贝),并设置有返回值参数
SqlParameter[] parameters = SqlServerHelper.GetSpParameterSet(ConnectionString, spName, true, parameterValues);
// 执行存储过程
SqlServerHelper.ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, spName, parameters);

// 存储过程执行后的返回值
return parameters[0].Value;
}

protected virtual TModel GetModel<TModel>(Func<DataReader, TModel> getModel, string spName, params object[] parameterValues)
where TModel : new()
{
TModel entity = new TModel();

// 自动获取存储过程参数(第二次后会取被缓存的一个拷贝),并设置没有返回值参数
SqlParameter[] parameters = SqlServerHelper.GetSpParameterSet(ConnectionString, spName, false, parameterValues);

// 执行存储过程
using (var reader = SqlServerHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, spName, parameters))
{
if (reader.Read())
{
// 读取数据
entity = getModel(reader);
}
}

return entity;
}

protected virtual List<TModel> GetModelList<TModel>(Func<DataReader, TModel> getModel, string spName, params object[] parameterValues)
where TModel : new()
{
List<TModel> list = new List<TModel>();

// 自动获取存储过程参数(第二次后会取被缓存的一个拷贝),并设置没有返回值参数
SqlParameter[] parameters = SqlServerHelper.GetSpParameterSet(ConnectionString, spName, false, parameterValues);

// 执行存储过程
using (var reader = SqlServerHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, spName, parameters))
{
while (reader.Read())
{
// 读取数据
TModel entity = getModel(reader);

list.Add(entity);
}
}

return list;
}

public virtual PagedList<TModel> GetPagedList<TModel>(Func<DataReader, TModel> getModel, PagedSqlParameters pagedSqlParameters)
where TModel : new()
{
if (pagedSqlParameters.PageSize < 1 || pagedSqlParameters.PageSize > 50)
{
pagedSqlParameters.PageSize = 10;
}

// 执行存储过程(SqlServerHelper内置的分页存储过程)
using (var reader = SqlServerHelper.ExecutePagedReader(ConnectionString, pagedSqlParameters))
{
List<TModel> list = new List<TModel>();
while (reader.Read())
{
// 读取数据
TModel model = getModel(reader);

list.Add(model);
}

return list.ToPagedList(reader.PageSize, reader.PageIndex, reader.RecordCount);
}
}
}

 

UserProvider
    ///<summary>
/// 用户接口实现
///</summary>
public sealed class UserProvider : ProviderBase, IUserProvider
{
public bool Add(string userName, string password, string passwordSalt, UserGender gender, string realName, string email, string mobile, UserStatus status)
{
object value = ExecuteNonQueryWithReturnValueParameter("SP_MDMS_User_Add", userName, password, passwordSalt, gender, realName, email, mobile, status);

return (Convert.ToInt32(value) > 0);
}

public bool EditById(Guid id, string password, string passwordSalt, UserGender gender, string realName, string email, string mobile, UserStatus status)
{
object value = ExecuteNonQueryWithReturnValueParameter("SP_MDMS_User_EditById", id, password, passwordSalt, gender, realName, email, mobile, status);

return (Convert.ToInt32(value) > 0);
}

public bool EditPasswordByUserName(string userName, string password, string passwordSalt)
{
object value = ExecuteNonQueryWithReturnValueParameter("SP_MDMS_User_EditPasswordByUserName", userName, password, passwordSalt);

return (Convert.ToInt32(value) > 0);
}

public bool DeleteByIds(Guid[] ids)
{
object value = ExecuteNonQueryWithReturnValueParameter("SP_MDMS_User_DeleteByIds", SqlServerHelper.ToCommaString(ids));

return (Convert.ToInt32(value) > 0);
}

public bool SetStatusByIds(Guid[] ids, UserStatus status)
{
object value = ExecuteNonQueryWithReturnValueParameter("SP_MDMS_User_SetStatusByIds", SqlServerHelper.ToCommaString(ids), (byte)status);

return (Convert.ToInt32(value) > 0);
}

public UserModel GetById(Guid id)
{
return GetModel(GetUserModel, "SP_MDMS_User_GetById", id);
}

public UserModel GetByUserName(string userName)
{
return GetModel(GetUserModel, "SP_MDMS_User_GetByUserName", userName);
}

public PagedList<UserModel> GetPagedList(string userName, UserGender? gender, UserStatus? status, int pageSize, int pageIndex)
{
PagedSqlParameters sqlParameters = new PagedSqlParameters()
{
SelectExpression = "*",
FromExpression = "[dbo].[User]",
MasterTable = "[dbo].[User]",
MasterPrimaryKey = "[Id]",
AutoIncrementKeyMode = false,
WhereExpression = string.Empty,
OrderExpression = "[CreateDate]",
Descending = true,
MaxPageIndex = 0,
PageSize = pageSize,
PageIndex = pageIndex
};

if (!string.IsNullOrEmpty(userName))
{
sqlParameters.WhereExpression += " AND [UserName] LIKE '%" + SqlServerHelper.EscapeLike(userName) + "%'";
}
if (gender.HasValue)
{
sqlParameters.WhereExpression += " AND [Gender]=" + ((byte)gender.Value).ToString();
}
if (status.HasValue)
{
sqlParameters.WhereExpression += " AND [Status]=" + ((byte)status.Value).ToString();
}

return GetPagedList(GetUserModel, sqlParameters);
}

private UserModel GetUserModel(DataReader reader)
{
return new UserModel
{
Id = reader.GetGuid("Id"),
UserName = reader.GetString("UserName").Trim(),
Password = reader.GetString("Password"),
PasswordSalt = reader.GetString("PasswordSalt"),
Gender = (UserGender)reader.GetByte("Gender"),
RealName = reader.GetString("RealName").Trim(),
Email = reader.GetString("Email"),
Mobile = reader.GetString("Mobile").Trim(),
Status = (UserStatus)reader.GetByte("Status"),
CreateDate = reader.GetDateTime("CreateDate")
};
}
}

.....其它省略....
 

四、子系统怎么与主数据管理系统整合?

 只要继承 MDMS.UserApiModule 项目里的ServiceContextBase类,就可以很轻松的实现用户的登录,退出,添加日志,读取权限等操作,其中主数据管理系统也作为了其中的一个子系统来管理了,可以参考此系统是怎么整合的,时间问题,不想再多写解说了。请谅解。

 

 另一文中讲解了此系统的权限设计方案:如何给多个子系统设计一个简单通用的权限管理方案?

 

转载于:https://www.cnblogs.com/kudy/archive/2011/11/07/2237802.html

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
软件详细信息 软件可建立并管理Access数据库、Xbase数据库、Excel数据库及Text文本数据库。要功能有: 一、字段开关与顺序控制功能。可控制数据显示表、记录排序表、浏览编辑状态及数据导出结果。换言之,只能显示、排序、编辑及导出被添加的字段,且显示、排序、编辑及导出结果的顺序与添加字段的顺序一致。 二、数据计算与编辑功能。包括按线性公式批量修改记录、按工程公式批量修改记录、浏览编辑记录、修改单元格记录、增加记录、删除记录、合并记录等。 三、通用查询与检索功能。除可在全程或设定的范围内管理记录外,还可设定过滤条件,对只符合条件及规定范围内的记录进行操作。 四、数据排序功能。排序的结果可导出为Access数据(MDB)、Excel数据(XLS)、文本数据(TXT)、Xbase数据(DBF)等格式。  五、数据比较功能。可比较两个表的结构属性及记录异同情况,也可比较同一表中两个字段的异同情况,并存储比较结果。  六、记录合并功能。可将数据表中某列(关键字段)具有相同值的所有记录数据进行合并。 七、记录连接功能。可将两个表中符合条件(两个表中各自选定的关键字段值相同)的所有记录连接生成一个新的表。 八、数据统计功能。可对表中数据以记录为单位进行汇总(横向统计)、也可以字段为单位进行汇总(纵向统计,即分类汇总)。统计的结果可导出为Access数据(MDB)、Excel数据(XLS)、文本数据(TXT)、Xbase数据(DBF)等格式。 九、数据导入导出功能。可将Access数据库、Xbase数据库、Excel数据库、Text文本数据库等四种格式的数据库格式进行相互导入导出。导出前可设置过滤条件、导出范围及导出字段开关与顺序。 十、文本数据分隔符转换功能。为了兼容除逗号以外的其它分隔符的文本文件,应用此模块进行分隔符转换(即替换),以适应本软件或用户其它软件的特殊要求。 十一、曲线显示与打印功能。不仅可显示任意字段变量随记录号的变化曲线,而且还可显示任意两个字段变量之间的关系曲线。显示的曲线可打印输出到WORD文档中。 十二、结构维护功能。可新建库、压缩库、增加表、删除表、修改表名、增加字段、删除字段、修改字段属性(包括字段名称、字段类型、字段尺寸)。 十三、密码管理功能。可管理有密码的数据库,并具有设置密码、修改密码、清除密码、破解密码等功能。 十四、管理非Access文件。包括Xbase、Excel、Text等类型的文件,并可对记录数据进行查询检索、编辑、统计、排序,且管理的结果可导出为mdb、dbf、txt、xls等格式。 十五、用户可根据实际应用情况,自定义软件的名称、数据处理路径、数据备份路径等,使数据管理更加个性化。鼠标经过大多数控件处,均有相关帮助与提示信息。软件可在菜单方式与集成方式两种界面之间自由切换,并根据屏幕分辨率软件自动调节窗体,使窗体始终保持最大的可视界面,建议屏幕分辨率设置为1024×768为最佳。 与9.1版相比,9.2版增加了本数据分隔符转换功能;进一步完善了导入导出功能,使导入导出成功率更高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值