Enterprise Solution 管理軟件開發框架流程實戰

1 定義模塊和功能

執行系統功能(SAUTSF),在系統主文件(System Master File SAMF)模塊中增長功能SAMFEM,Employee Master。html

給有權限的用戶組分配功能SAMFEM的權限,包含新增,刪除,修改,打印,過賬權限,這是功能權限。數據庫

若是須要增長字段權限,好比能夠編輯員工薪資字段,應該修改用戶表(User)增長權限字段。服務器

2 定義導航菜單

把增長的功能放置到合適的功能菜單中,菜單項的位置根據須要而定。好比員工主文件,能夠放置到主檔定義中,還能夠放置一份到人事管理的設定菜單項中。定義一個菜單項位置,系統會生成三個地方的導航菜單項:標題欄下的主菜單(ToolStrip), 導航樹右邊的列表視圖(ListView),導航圖的上下文菜單(ContextMenu),三種方式幫助用戶快速查找與執行功能。併發

3 設計數據庫表

以員工表爲例子,員工表的數據庫腳本以下:ide

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數據表,最後點擊生成源代碼文件。fetch

image

通常狀況下用默認的命名規則便可。好比Item_No映射的實體字段名是ItemNo,默認去掉下劃線。ui

5 實體數據訪問接口與實現生成

用Template目錄中的Code Smith模板生成接口與實現類,代碼以下:this

數據接口類:編碼

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);
    }

數據實現類:spa

[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。

image

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生成程序。

image

執行.NET Reactor批處理腳本,將生成的文件複製到客戶的更新服務器中。

相關文章
相關標籤/搜索