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 管理软件开发框架流程实战的更多相关文章

  1. Enterprise Solution 企业管理软件开发框架

    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架 Enterprise Solution 是一套管理软件开发框架,在 ...

  2. Enterprise Solution 应用程序开发框架培训

    一.系统架构 C# .NET 4.0 + Win Form + SQL Server 2005 二.五大核心模块 (菜单设计器Menu Designer,查询设计器Query Designer,报表设 ...

  3. 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 数据库 ...

  4. Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架

    Enterprise Solution 是一套管理软件开发框架,在这个框架基础上开发出一套企业资源计划系统Enterprise Edition. 现将Enterprise Solution开发过程中遇 ...

  5. Enterprise Solution 企业资源计划管理软件 C/S架构,支持64位系统,企业全面应用集成,制造业信息化

    Enterprise Solution是一套完整的企业资源计划系统,功能符合众多制造业客户要求.系统以.NET Framework技术作为开发架构,完善的功能可有效地帮助企业进行运营策划,减低成本,如 ...

  6. 从国内流程管理软件市场份额看中国BPM行业发展

    随着互联网+.中国制造2025.工业4.0等国家战略的支持与引导,企业在数字经济时代的信息化表现惊人,越来越多企业认识到,对于企业的发展来说,信息自动化远远还不够,企业的战略.业务和IT之间需保持高度 ...

  7. Enterprise Solution 界面设计规范

    Enteprise Solution有一套自己的界面设计规范,也是很多年(10年以上)管理软件界面精华的积累.没有一个软件从一开始就很善于界面设计,许多个小小的改善,比如控件位置的移动,控件摆放顺序的 ...

  8. 仿OpenStack开发云计算管理软件

    仿OpenStack开发云计算管理软件 使用Python语言开发一套类似OpenStack的云计算管理平台LouCloud,具备基本的用户,服务器,镜像与 虚拟机管理功能,学习IaaS,虚拟化,Lib ...

  9. CSLA .NET是一个.NET软件开发框架

    CSLA .NET是一个.NET软件开发框架,帮助开发者“为Windows.Web.面向服务和工作流等应用构建强大和可维护的业务逻辑层”. CSLA是Component-based, Scalable ...

随机推荐

  1. python走起之第九话

    协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来 ...

  2. B-树,B+树,B*树详解

    B-树 B-树是一种多路搜索树(并不一定是二叉的) 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树.B_树). 一棵m阶B树(b ...

  3. C/C++程序员常去网站

    www.codeproject.comwww.codegru.comwww.chinaunix.netwww.csdn.netwww.vckbase.com http://www.google.com ...

  4. Python+Google Geocoding

    本文主要介绍使用Python调用Google Geocoding API进行地址到地理坐标的转换. Google Geocoding参考https://developers.google.com/ma ...

  5. “你没有权限登录JIRA”的解决办法

    为了更好的做部门的项目管理,部门老大让运维部署了一个jira系统.这两天让我试用并摸索如何用. jira默认的用户组有 jira-administrators.jira-developers.jira ...

  6. HTML超链接

    打开网页在 想要查看的位置右键单击   审查元素  则可以查看代码    点击图片右键单独打开  则可以查看图片位置 一.超链接 a标签   <a href="地址"> ...

  7. iOS 访问粘贴板

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = self.label.text;

  8. WebService – 2.动态调用WebService

    在本节课程中,将演示如何通过程序动态添加.调用.编译.执行WebService并返回结果. WebService动态调用示意图 WebService相关知识 代码文档对象模型CodeDom的使用 编程 ...

  9. Python学习一入门

    一.打印Hello和多行文本 print 打印 后跟单引号或者双引号 多行:3个单引号或者3个双引号 二.算术运算 2.1.加减乖法 默认1/2=0 如果需要小数运算,则需要一个运算术上加.或者.0 ...

  10. 查询功能:yum [list|info|search|provides|whatprovides] 参数

    [root@www ~]# yum [option] [查询工作项目] [相关参数] 选项与参数: [option]:主要的选项,包括有:   -y :当 yum 要等待使用者输入时,这个选项可以自动 ...