转载

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数据表,最后点击生成源代码文件。

Enterprise Solution 管理软件开发框架流程实战

一般情况下用默认的命名规则即可。比如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。

Enterprise Solution 管理软件开发框架流程实战

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");  } 
正文到此结束
Loading...