Enterprise Solution 管理软件开发框架流程实战
1 定义模块和功能
执行系统功能(SAUTSF),在系统主文件(System Master File SAMF)模块中增加功能SAMFEM,Employee Master。
给有权限的用户组分配功能SAMFEM的权限,包含新增,删除,修改,打印,过帐权限,这是功能权限。
如果需要增加字段权限,比如可以编辑员工薪资字段,应该修改用户表(User)增加权限字段。
2 定义导航菜单
把增加的功能放置到合适的功能菜单中,菜单项的位置根据需要而定。比如员工主文件,可以放置到主档定义中,还可以放置一份到人事管理的设定菜单项中。定义一个菜单项位置,系统会生成三个地方的导航菜单项:标题栏下的主菜单(ToolStrip), 导航树右边的列表视图(ListView),导航图的上下文菜单(ContextMenu),三种方式帮助用户快速查找与执行功能。
3 设计数据库表
以员工表为例子,员工表的数据库脚本如下:
CREATE TABLE [dbo].[Employee]
(
[Recnum] [numeric] (18, 0) NOT NULL IDENTITY(1, 1),
[EmployeeNo] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Department] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[ProductionGroup] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[CompanyCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[BranchCode] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Account] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Password] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Gender] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Birthday] [datetime] NULL,
[Mobile] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Address] [nvarchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[HomeTelephone] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Post] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Type] [char] (4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Suspended] [char] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL CONSTRAINT [DF__tEmployee__Enabl__32CB82C6] DEFAULT ((1)),
[JobTitle] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[JoinDate] [datetime] NULL,
[LeftDate] [datetime] NULL,
[Photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Employee] WITH NOCHECK ADD CONSTRAINT [CKC_TYPE_TEMPLOYE] CHECK (([Type]=(1) OR [Type]=(0)))
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT [PK_TEMPLOYEE] PRIMARY KEY CLUSTERED ([EmployeeNo]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Employee] WITH NOCHECK ADD CONSTRAINT [FK_Employee_Department] FOREIGN KEY ([Department]) REFERENCES [dbo].[Department] ([DepartmentCode])
GO
ALTER TABLE [dbo].[Employee] NOCHECK CONSTRAINT [FK_Employee_Department]
GO
4 LLBL Gen Pro生成实体映射
执行程序LLBL Gen Pro,连接到数据库并添加Employee数据表,最后点击生成源代码文件。
一般情况下用默认的命名规则即可。比如Item_No映射的实体字段名是ItemNo,默认去掉下划线。
5 实体数据访问接口与实现生成
用Template目录中的Code Smith模板生成接口与实现类,代码如下:
数据接口类:
public interface IEmployeeManager
{
EmployeeEntity GetEmployee(System.String EmpNo);
EmployeeEntity GetEmployee(System.String EmpNo, IPrefetchPath2 prefetchPath);
EmployeeEntity GetEmployee(System.String EmpNo, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList); EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket);
EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression);
EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath);
EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList); EmployeeEntity SaveEmployee(EmployeeEntity employee);
EmployeeEntity SaveEmployee(EmployeeEntity employee, EntityCollection entitiesToDelete);
EmployeeEntity SaveEmployee(EmployeeEntity employee, EntityCollection entitiesToDelete, string seriesCode); void DeleteEmployee(EmployeeEntity employee); bool IsEmployeeExist(System.String EmpNo);
bool IsEmployeeExist(IRelationPredicateBucket filterBucket);
int GetEmployeeCount(IRelationPredicateBucket filterBucket); EmployeeEntity CloneEmployee(System.String EmpNo);
void PostEmployee(System.String EmpNo);
void PostEmployee(EmployeeEntity employee);
}
数据实现类:
[RemoteService("EmployeeManager")]
public class EmployeeManager : Foundation.Common.ManagerBase, IEmployeeManager
{
public EmployeeEntity GetEmployee(System.String EmpNo)
{
IPrefetchPath2 prefetchPath = new PrefetchPath2((int)EntityType.EmployeeEntity);
prefetchPath.Add(EmployeeEntity.PrefetchPathEmployeeTrainings);
return GetEmployee(EmpNo, prefetchPath);
} public EmployeeEntity GetEmployee(System.String EmpNo, IPrefetchPath2 prefetchPath)
{
return GetEmployee(EmpNo, prefetchPath, null);
} public EmployeeEntity GetEmployee(System.String EmpNo, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList)
{
EmployeeEntity employee = new EmployeeEntity(EmpNo);
using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())
{
bool found = adapter.FetchEntity(employee, prefetchPath, null, fieldList);
if (!found) throw new Foundation.Common.RecordNotFoundException("Invalid Employee");
}
return employee;
} public EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket)
{
return GetEmployeeCollection(filterBucket, null);
} public EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression)
{
return GetEmployeeCollection(filterBucket, sortExpression, null);
} public EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath)
{
return GetEmployeeCollection(filterBucket, sortExpression, prefetchPath, null);
} public EntityCollection GetEmployeeCollection(IRelationPredicateBucket filterBucket, ISortExpression sortExpression, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList)
{
EntityCollection employeeCollection = new EntityCollection(new EmployeeEntityFactory());
using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())
{
adapter.FetchEntityCollection(employeeCollection, filterBucket, 0, sortExpression, prefetchPath, fieldList);
}
return employeeCollection;
} public EmployeeEntity SaveEmployee(EmployeeEntity Employee)
{
return SaveEmployee(Employee, null);
} public EmployeeEntity SaveEmployee(EmployeeEntity Employee, EntityCollection entitiesToDelete)
{
return SaveEmployee(Employee, entitiesToDelete, string.Empty);
} public EmployeeEntity SaveEmployee(EmployeeEntity Employee, EntityCollection entitiesToDelete, string seriesCode)
{
using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())
{
try
{
adapter.StartTransaction(IsolationLevel.ReadCommitted, "SaveEmployee");
adapter.SaveEntity(Employee, true, false); IEmployeeTrainingManager trainingManager = ClientProxyFactory.CreateProxyInstance<IEmployeeTrainingManager>();
foreach (var employeeTraining in Employee.EmployeeTrainings)
{
trainingManager.SaveEmployeeTraining(employeeTraining);
}
adapter.Commit();
}
catch
{
adapter.Rollback();
throw;
}
}
return Employee;
} public void DeleteEmployee(EmployeeEntity Employee)
{
using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())
{
if (!adapter.IsEntityExist<EmployeeEntity>(Employee))
return; try
{
adapter.StartTransaction(IsolationLevel.ReadCommitted, "DeleteEmployee");
IEmployeeTrainingManager trainingManager = ClientProxyFactory.CreateProxyInstance<IEmployeeTrainingManager>();
foreach (var employeeTraining in Employee.EmployeeTrainings)
{
trainingManager.DeleteEmployeeTraining(employeeTraining);
}
adapter.DeleteEntity(Employee);
adapter.Commit();
}
catch
{
adapter.Rollback();
throw;
}
}
} public bool IsEmployeeExist(System.String EmpNo)
{
RelationPredicateBucket filterBucket = new RelationPredicateBucket();
filterBucket.PredicateExpression.Add(EmployeeFields.EmployeeNo == EmpNo);
return IsEmployeeExist(filterBucket);
} public bool IsEmployeeExist(IRelationPredicateBucket filterBucket)
{
return (GetEmployeeCount(filterBucket) > 0);
} public int GetEmployeeCount(IRelationPredicateBucket filterBucket)
{
using (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())
{
return adapter.GetDbCount<EmployeeEntity>(filterBucket);
}
} public EmployeeEntity CloneEmployee(System.String EmpNo)
{
EmployeeEntity source = this.GetEmployee(EmpNo);
EmployeeEntity employee = (EmployeeEntity)CloneEntity(source);
return employee;
} public void PostEmployee(System.String EmpNo)
{
return;
} public void PostEmployee(EmployeeEntity Employee)
{
return;
}
}
6 界面设计,控件数据绑定,查找与钻取
Windows窗体设计的主要流程步骤
1) 拖一个EntityCollection组件到界面中,这个组件来自于LLBL Gen Pro生成的数据库映射项目。
设置EntityFactoryToUse=Kingston.FactoryClasses.EmployeeEntityFactory。
2) 拖多个BindingSource组件到界面。每一层控件都需要一个BindingSource组件,如果界面是单笔数据操作,还需要拖一个空的BindingSource组件到界面中,并将它设为窗体的NavigatorBindingSource。
3) 依次绑定控件与数据源组件的属性。要注意选对控件,TextEditor,NumbericEditor。对于必须输入值的控件,要设置Required=true,对于映射到主键字段的控件,要设AutoFind=true。
4) 给控件增加查找与钻取。
5) 设置控件的tab index。
7 验证和计算逻辑
1) 增加实体属性的默认值。修改文件EmployeeEntity.Implementation.cs
public partial class EmployeeEntity
{
protected override void OnInitialized()
{
base.OnInitialized(); // Assign default value for new entity
if (Fields.State == EntityState.New)
{
#region DefaultValue // __LLBLGENPRO_USER_CODE_REGION_START DefaultValue
this.Fields[(int) EmployeeFieldIndex.Suspended].CurrentValue = false;
// __LLBLGENPRO_USER_CODE_REGION_END #endregion
2) 增加自动带值。比如输入员工所在的部门编码,要自动带入部门名称。
private void OnChangeDepartment(string originalValue)
{
IDepartmentManager departmentManager =CreateProxyInstance<IDepartmentManager>();
if (departmentManager.IsDepartmentExist(Department))
{
ExcludeIncludeFieldsList fieldList = new ExcludeIncludeFieldsList(false);
fieldList.Add(DepartmentFields.FullName);
DepartmentEntity department = departmentManager.GetDepartment(Department, null, fieldList);
this.DepartmentName = department.FullName;
}
}
3) 增加验证代码,对需要验证的属性值进行验证。
值验证:
public override bool ValidateFieldValue(IEntityCore involvedEntity, int fieldIndex, object value)
{
bool result = base.ValidateFieldValue(involvedEntity, fieldIndex, value); if (!result) return false;
switch ((EmployeeFieldIndex)fieldIndex)
{
case EmployeeFieldIndex.Department:
return ValidateDepartment((string)value, (EmployeeEntity)involvedEntity);
break;
private bool ValidateDepartment(string value, EmployeeEntity EGEntity)
{
if (!string.IsNullOrWhiteSpace(value))
{
IDepartmentManager departmentManager = CreateProxyInstance<IDepartmentManager>();
departmentManager.ValidateDepartment(value);
}
return true;
}
删除验证:
public override void ValidateEntityBeforeDelete(IEntityCore involvedEntity)
{
base.ValidateEntityBeforeDelete(involvedEntity);
EmployeeEntity employeeEntity = (EmployeeEntity)involvedEntity;
ISalesmanManager salesmanManager = CreateProxyInstance<ISalesmanManager>(); RelationPredicateBucket filterBucket = new RelationPredicateBucket();
filterBucket.PredicateExpression.Add(SalesmanFields.EmployeeNo == employeeEntity.EmployeeNo);
if (salesmanManager.IsSalesmanExist(filterBucket))
{
throw new FieldValidationException("Employee No. already used in salesman");
}
保存前验证:
public override void ValidateEntityBeforeSave(IEntityCore involvedEntity)
{
base.ValidateEntityBeforeSave(involvedEntity);
EmployeeEntity employeeEntity = (EmployeeEntity)involvedEntity; if (string.IsNullOrWhiteSpace(employeeEntity.EmployeeNo))
{
throw new EntityValidationException("Employee No. is required");
}
8 生成并发布程序
打开Visual Studio 2015或用MSBUILD生成程序。
执行.NET Reactor批处理脚本,将生成的文件复制到客户的更新服务器中。
Enterprise Solution 管理软件开发框架流程实战的更多相关文章
- Enterprise Solution 企业管理软件开发框架
Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架 Enterprise Solution 是一套管理软件开发框架,在 ...
- Enterprise Solution 应用程序开发框架培训
一.系统架构 C# .NET 4.0 + Win Form + SQL Server 2005 二.五大核心模块 (菜单设计器Menu Designer,查询设计器Query Designer,报表设 ...
- Enterprise Solution 3.1 企业应用开发框架 .NET ERP/CRM/MIS 开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms
行业:基于数据库的制造行业管理软件,包含ERP.MRP.CRM.MIS.MES等企业管理软件 数据库平台:SQL Server 2005或以上 系统架构:C/S 开发技术 序号 领域 技术 1 数据库 ...
- Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
Enterprise Solution 是一套管理软件开发框架,在这个框架基础上开发出一套企业资源计划系统Enterprise Edition. 现将Enterprise Solution开发过程中遇 ...
- Enterprise Solution 企业资源计划管理软件 C/S架构,支持64位系统,企业全面应用集成,制造业信息化
Enterprise Solution是一套完整的企业资源计划系统,功能符合众多制造业客户要求.系统以.NET Framework技术作为开发架构,完善的功能可有效地帮助企业进行运营策划,减低成本,如 ...
- 从国内流程管理软件市场份额看中国BPM行业发展
随着互联网+.中国制造2025.工业4.0等国家战略的支持与引导,企业在数字经济时代的信息化表现惊人,越来越多企业认识到,对于企业的发展来说,信息自动化远远还不够,企业的战略.业务和IT之间需保持高度 ...
- 流程及迭代驱动测试管理软件, itest 发布到开源中国
itest 源码已发布到码云 ,项目已被开源中国收录!详见 https://www.oschina.net/p/itest-cn 测试人自己开发,汇聚10年沉淀,独创流程驱动测试.度量展现测试人价值 ...
- Enterprise Solution 界面设计规范
Enteprise Solution有一套自己的界面设计规范,也是很多年(10年以上)管理软件界面精华的积累.没有一个软件从一开始就很善于界面设计,许多个小小的改善,比如控件位置的移动,控件摆放顺序的 ...
- 仿OpenStack开发云计算管理软件
仿OpenStack开发云计算管理软件 使用Python语言开发一套类似OpenStack的云计算管理平台LouCloud,具备基本的用户,服务器,镜像与 虚拟机管理功能,学习IaaS,虚拟化,Lib ...
随机推荐
- Markdown 图片助手-MarkdownPicPicker
title: Markdown 图片助手 v0.1 toc: true comments: true date: 2016-06-04 16:40:06 tags: [Python, Markdown ...
- excel 日期/数字格式不生效需要但双击才会生效的解决办法
原因: Excel2007设置过单元格格式后,并不能立即生效必须挨个双击单元格,才能生效.数据行很多.效率太低. 原因:主要是一些从网上拷贝过来的日期或数字excel默认为文本格式或特殊-中文数字格式 ...
- nodejs创建http服务器
之前有简单介绍nodejs的一篇文章(http://www.cnblogs.com/fangsmile/p/6226044.html) HTTP服务器 Node内建有一个模块,利用它可以很容易创建基本 ...
- iOS逆向工程之Theos
如果你对iOS逆向工程有所了解,那么你对Tweak并不陌生.那么由Tweak我们又会引出Theos, 那么什么是Theos呢,简单一句话,Theos是一个越狱开发工具包,Theos是越狱开发工具的首先 ...
- node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法
1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...
- PHP static静态属性和静态方法
这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置,这样就非常容易理解了.静态属性.方法(包括静态与非静态)在内 ...
- Html 制作相册
本文主要讲述采用Html5+jQuery+CSS 制作相册的小小记录. 主要功能点: Html5进行布局 调用jQuery(借用官网的一句话:The Write Less, Do More)极大的简化 ...
- Android Retrofit 2.0 使用-补充篇
推荐阅读,猛戳: 1.Android MVP 实例 2.Android Retrofit 2.0使用 3.RxJava 4.RxBus 5.Android MVP+Retrofit+RxJava实践小 ...
- EntityFramework 6 + Mysql 生成POCOs
问题 使用EDMX文件 EF Power Tools参数不正确的解决方法 对于"异常来自 HRESULT:0x80070057 (E_INVALIDARG)",有方法说" ...
- 一种简单的CQRS架构设计及其实现
一.为什么要实践领域驱动? 近一年时间我一直在思考一个问题:"如何设计一个松耦合.高伸缩性.易于维护的架构?".之所以有这样的想法是因为我接触的不少项目都是以数据库脚本来实现业务逻 ...