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();
注意事项:
- 不要直接使用SQLHelper对象
- 不要使用被标记为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使用说明
- 新增
- 选择或输入pdm文件路径,路径中不可出现中文
- 输入表名
- 输入作者
- 点击生成按钮
- 在符合架构的Service目录下创建C#文件,文件命名规则“{表名}Service.auto.cs”。复制“输出窗口1”的代码粘贴到此文件中。这个文件中的代码禁止编辑。
- 在同一目录下创建C#文件,文件命名规则“{表名}Service.cs”。复制“输出窗口2”的代码粘贴到此文件中。这个文件中的代码允许编辑。
- 在符合架构的Model目录下创建C#文件,文件命名规则为”{表名}.cs“。复制”模型输出“窗口的代码粘贴到此文件中。这个文件中的代码只允许在末尾追加内容。
- 在同一目录下创建C#文件,文件命名规则“{表名}Parameter.cs”。复制”参数输出“窗口的代码粘贴到此文件中。这个文件中的代码允许编辑。
- 在同一目录下创建C#文件,文件命名规则“{表名}ParameterWithPagenation.cs”。复制”分页参数输出“窗口的代码粘贴到此文件中。这个文件中的代码允许编辑。
- 修改
- 选择或输入pdm文件路径,路径中不可出现中文
- 输入表名
- 输入作者
- 点击生成按钮
- 复制“输出窗口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); }
新写的代码不可再使用BaseSevice_Obsolete.cs文件中的资源(VS有已过时的警告提示)。
所有Service类现在都可以按照工厂系统的模式写代码了,数据库访问对象的属性为Database,因为名称_db被占用了。
Service类内部禁止使用事务,会导致事务管理混乱。如果确实需要事务,可调用
Database.UsingTransaction函数如果一个Service类要参与事务,必须修改这个类的构造函数,启用SQLHelperType.V2。具体修改方法为:
增加以下构造函数,例如EmployeeService:
public class EmployeeService : BaseService { public EmployeeService() : base(SQLHelperType.V2) { } }
尽快去除这个类中过时的代码,尤其是直接使用SQLHelper的代码,混用会导致不同函数使用不同的底层数据库连接;事务不起作用;资源争夺等问题。
查找这个类的所有引用,修改为前文描述的除用法3以外的其它用法
修改记录
- BaseService和CommonService移到了QueryInterface.DAL.Common目录下,命名空间保持不变。
- 所有原先放在DAL目录下的Service类移动到了QueryInterface.DAL.Misc目录下,命名空间保持不变
- SQLHelper等更底层的类移动到了QueryInterface.DAL.Core目录下,命名空间保持不变,开发业务时不需要动这个目录下的代码。
- BaseService中的代码已重构,合理的代码保留在BaseService.cs文件中,过时的代码移动到BaseService_Obsolete.cs文中,不应该在BaseService中的工具类函数移动到BaseService_Helper.cs文件中,这些函数都还保留在BaseService类里。
- 只要Service类没有使用SQLHelperType.V2,老的代码即使没有调用OpenConnection和CloseConnection也没关系。一旦改造为SQLHelperType.V2,必须修改所有引用代码。