QueryInterface.DAL架构说明:

[TOC]

使用

用法1-无事务(推荐用法)

//所有被调用的Service层对象都必须使用SQLHelperType.V2
using (var serviceFactory = new ServiceFactory())
{
    //所有Service对象都使用同一个底层数据库连接
    var employeeService = serviceFactory.GetService<EmployeeService>();
    var hospitalService = serviceFactory.GetService<HospitalService>();
    var orderService = serviceFactory.GetService<OrderService>();
    //使用前无需开启连接
    //var employees = employeeService.SelectEmployees();
    //var hospitals = hospitalService.SelectHospitals();
    //orderService.InsertOrders();
    //使用后无需清理
}

用法1-事务无返回(推荐用法)

//所有被调用的Service层对象都必须使用SQLHelperType.V2
using (var serviceFactory = new ServiceFactory())
{
    //所有Service对象都使用同一个底层数据库连接
    var employeeService = serviceFactory.GetService<EmployeeService>();
    var hospitalService = serviceFactory.GetService<HospitalService>();
    var orderService = serviceFactory.GetService<OrderService>();
    //使用前无需开启连接

    //开启ReadCommitted事务,执行函数,并自动提交事务
    serviceFactory.Database.UsingTransaction(IsolationLevel.ReadCommitted, transaction =>
    {
        //var employees = employeeService.SelectEmployees();
        //var hospitals = hospitalService.SelectHospitals();
        //orderService.InsertOrders();  
        //throw new TransactionRollbackException(true); //如果要回滚事务
    });

    //使用后无需清理
}

用法1-事务带返回(推荐用法)

//所有被调用的Service层对象都必须使用SQLHelperType.V2
using (var serviceFactory = new ServiceFactory())
{
    //所有Service对象都使用同一个底层数据库连接
    var employeeService = serviceFactory.GetService<EmployeeService>();
    var hospitalService = serviceFactory.GetService<HospitalService>();
    var orderService = serviceFactory.GetService<OrderService>();
    //使用前无需开启连接

    //开启ReadCommitted事务,执行函数,并自动提交事务
    serviceFactory.Database.UsingTransaction(IsolationLevel.ReadCommitted, transaction =>
    {
        //var employees = employeeService.SelectEmployees();
        //return employees;
    }, e =>
    {
        //处理异常
        //ExceptionLog.Write(e);
        //指定必要的返回值
        return null;
    }
    );

    //使用后无需清理
}

用法2(兼容用法)

//以此法创建的不同Service对象,使用不同的底层数据库连接,需要分别开启和关闭
using (var employeeService = new EmployeeService())
{
    //使用前需开启连接
    employeeService.OpenConnection();
    //var employees = employeeService.SelectEmployees();
}

用法3(原始用法)

//这是义齿软件原先的写法,Service层必须使用SQLHelperType.V1,否则会出现资源泄露
var employeeService = new EmployeeService();
//var employees = employeeService.SelectEmployees();

注意事项:

  1. 不要直接使用SQLHelper对象
  2. 不要使用被标记为Obsolete的对象(VS有已过时的警告提示)

开发

原则

  • DAL层原则上来说避免涉及业务逻辑,禁止操控事务。但在目前阶段,DAL层的类应分为两组:1、涉及业务逻辑的Service类;2、不涉及业务逻辑的单表增删改查Service类(由AutoCode工具生成,见下文AutoCode使用说明)

  • Service类必须继承BaseService

  • Service类中涉及业务逻辑适合封装成独立函数的代码,可以写成静态函数
  • Service类禁止互相调用
  • Service类禁止持有ISQLHelper对象的引用,但可以通过基类的Database属性访问
  • Service类中的实例函数禁止实例化ISQLHelper或任何Service类。静态函数可以实例化ISQLHelper,但必须通过SQLHelperFactory实例化。
  • Service类禁止控制底层数据库连接
  • BLL层可能同时用到的Service类,必须统一使用SQLHelperType.V1或SQLHelperType.V2。BLL层禁止同时使用基于不同SQLHelperType的Service类。

架构

QueryInterface.DAL

Common

​ BaseService,所有DAL层都要继承的基类,包含业务逻辑

​ CommonService,大量未归类的有重用价值的函数,包含业务逻辑

Core

​ 比DAL层更低一层的代码,开发DAL时禁止修改此目录代码

Customer
DataQuery
Digital
Employee
Finance
Management
Misc
Production
ProductMgt
Quality
Setting

AutoCode使用说明

  1. 新增
    1. 选择或输入pdm文件路径,路径中不可出现中文
    2. 输入表名
    3. 输入作者
    4. 点击生成按钮
    5. 在符合架构的Service目录下创建C#文件,文件命名规则“{表名}Service.auto.cs”。复制“输出窗口1”的代码粘贴到此文件中。这个文件中的代码禁止编辑。
    6. 在同一目录下创建C#文件,文件命名规则“{表名}Service.cs”。复制“输出窗口2”的代码粘贴到此文件中。这个文件中的代码允许编辑。
    7. 在符合架构的Model目录下创建C#文件,文件命名规则为”{表名}.cs“。复制”模型输出“窗口的代码粘贴到此文件中。这个文件中的代码只允许在末尾追加内容。
    8. 在同一目录下创建C#文件,文件命名规则“{表名}Parameter.cs”。复制”参数输出“窗口的代码粘贴到此文件中。这个文件中的代码允许编辑。
    9. 在同一目录下创建C#文件,文件命名规则“{表名}ParameterWithPagenation.cs”。复制”分页参数输出“窗口的代码粘贴到此文件中。这个文件中的代码允许编辑。
  2. 修改
    1. 选择或输入pdm文件路径,路径中不可出现中文
    2. 输入表名
    3. 输入作者
    4. 点击生成按钮
    5. 复制“输出窗口1”的代码覆盖相应文件的所有代码
    6. 复制”模型输出“的代码覆盖相应文件的(自动生成的)前半部分

注意事项

  1. 所有Service类都继承BaseService,BaseService实现了IDispose接口,因此所有Service类现在都需要释放。如果Service类有资源需要Dispose,在Service类中增加以下函数:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            //释放托管对象
        }
        //释放非托管对象
        //BaseService目前未实现释放非托管对象流程所必要的析构函数,如存在非托管对象,在BaseService下增加析构函数,调用Dispose(false),并在BaseService的IDisposable.Dispose()函数最后增加GC.SuppressFinalize(this)
        base.Dispose(true);
    }
    
  1. 新写的代码不可再使用BaseSevice_Obsolete.cs文件中的资源(VS有已过时的警告提示)。

  2. 所有Service类现在都可以按照工厂系统的模式写代码了,数据库访问对象的属性为Database,因为名称_db被占用了。

  3. Service类内部禁止使用事务,会导致事务管理混乱。如果确实需要事务,可调用Database.UsingTransaction函数

  4. 如果一个Service类要参与事务,必须修改这个类的构造函数,启用SQLHelperType.V2。具体修改方法为:

    1. 增加以下构造函数,例如EmployeeService:

      public class EmployeeService : BaseService
      {
          public EmployeeService()
              : base(SQLHelperType.V2)
          {
          }
      }
      
  1. 尽快去除这个类中过时的代码,尤其是直接使用SQLHelper的代码,混用会导致不同函数使用不同的底层数据库连接;事务不起作用;资源争夺等问题。

  2. 查找这个类的所有引用,修改为前文描述的除用法3以外的其它用法

修改记录

  1. BaseService和CommonService移到了QueryInterface.DAL.Common目录下,命名空间保持不变。
  2. 所有原先放在DAL目录下的Service类移动到了QueryInterface.DAL.Misc目录下,命名空间保持不变
  3. SQLHelper等更底层的类移动到了QueryInterface.DAL.Core目录下,命名空间保持不变,开发业务时不需要动这个目录下的代码。
  4. BaseService中的代码已重构,合理的代码保留在BaseService.cs文件中,过时的代码移动到BaseService_Obsolete.cs文中,不应该在BaseService中的工具类函数移动到BaseService_Helper.cs文件中,这些函数都还保留在BaseService类里。
  5. 只要Service类没有使用SQLHelperType.V2,老的代码即使没有调用OpenConnection和CloseConnection也没关系。一旦改造为SQLHelperType.V2,必须修改所有引用代码。

results matching ""

    No results matching ""