从最初做JAVA开发到现在致力于.NET平台,经手的大大小小的项目也不在少数。刚开始每写成一个程序还能获得不少的成就感,但随着开发年限的增加、项目代码行的增加,写代码更多时候变成一种糊口的工具而非兴趣时,越来越被大量相似的SQL搅得头晕脑胀,尤其维护旧程序时,对SQL的调试更是让人头大。于是,一直致力于找出一个方法,可以不用每次都去编写那些烦人的SQL。
答案是肯定的,JAVA平台下有个Hibernate的ORM框架,它应该是最早的一个成熟的ORM软件,貌似可以解决我的问题。迫不及待的下载、使用MyEclipse去写测试程序,却发现并不如想象中的好,对我来说,最大的障碍在于那个XML配置文件。借助于IDE,配置工作或许还不是太繁琐,但脱离IDE之后,我发现对这个配置文件维护的困难绝对不在直接维护SQL命令之下。当然,好处还是有的,比如不用去调试每一条SQL。
虽然不太情愿,但毕竟脱离IDE的情况还是很少,所以也就“爱用不用”地用了一段时间。
之后,机缘巧合的转向.NET平台,从.NET Framework 1.1和VS2003开始,到现在的.NET Framework 2.0和VS2005,随着在.NET平台开发经验的日渐丰富,对C#特性越来越全面的了解,终于决定要自己写一个更加符合C#口味的ORM框架,完全的面向对象,更加简洁,更加高效,对IDE的智能感知支持更好(早期绑定) 。
一起来看看它的工作方式。
假设有一个员工表,字段为 id,employee_id,name,department_id
有一个实体类EmployeeInfo与上表各字段对应
现在我们需要为这个表写一个访问类,提供对数据库的增、删、改、查工作。
下面是实现以上功能的所有代码:
internal override ColumnParameter[] FillColumnParameters(EmployeeInfo entity) {
return base .BuildColumnParameter(
entity.ID,
entity.EmployeeID,
entity.Name,
entity.DepartmentID
);
}
public override string TableName {
get { return " employee_table " ; }
}
public override TableColumnCollection TableColumns {
get {
TableColumnCollection list = new TableColumnCollection( 4 );
list.AddRange( new TableColumn[] {
new TableColumn( " id " , true ), // 自增只读字段
new TableColumn( " employee_id " ),
new TableColumn( " name " ),
new TableColumn( " department_id " )
});
return list;
}
}
internal override EmployeeInfo BuildEntity(MySqlDataReader reader, int startIndex) {
EmployeeInfo info = new EmployeeInfo();
info.ID = reader.GetInt32( 0 );
info.EmployeeID = reader.GetString( 1 );
info.Name = reader.GetString( 2 );
info.DepartmentID = DataReadyUtility.GetInt32(reader, 3 );
return info;
}
}
从上面的代码可以看出,对一个独立表的访问,只需重写抽象基类的4个方法即可,可实现以下功能:
- 按主键获取一个数据行 GetByPrimaryKey(object)
- 获取数据表的所有记录 GetAll()
- 查询 Search(SearchConditionCollection, ...)
- 分页查询 Search(SearchConditionCollection, int, int, ...)
- 保存 Save(EmployeeInfo)
- 按主键值修改 Modify(...)
- 按条件修改 Modify(SearchConditionCollection, ...)
- 按主键删除 Delete(...)
- 按查询条件删除 Delete(SearchConditionCollection, ...)
下面的代码是对EmployeeTable类的扩充,使它具有足够多的功能:
// 修改员工名字
public int ChangeName( int id, string name) {
EmployeeInfo info = new EmployeeInfo();
info.Name = name;
// 使用ModifyBounds.None表示仅修改后面指定的字段 TableColumns["name"]
return base .Modify(id, info, ModifyBounds.None, TableColumns[ " name " ]);
}
// 按名字获取员工,不分页
public IList < EmployeeInfo > GetByName( string name) {
SearchConditionCollection filter = new SearchCoditionCollection();
// 按Like查询name字段
filter.add( new SearchCondition( " name " , new ColumnComparison(SqlOperator.Like, name)));
return base .Search(filter);
}
// 按名字获取员工,并分页 。输出不分页情况下的记录总数,供前台分页使用
public IList < EmployeeInfo > GetByName( string name, int pageSize, int pageIndex, out int itemCount) {
SearchConditionCollection filter = new SearchCoditionCollection();
// 按Like查询name字段
filter.add( new SearchCondition( " name " , new ColumnComparison(SqlOperator.Like, name)));
return base .Search(filter, pageSize, pageIndex, out itemCount);
}
}
最后就是对上面类各个方法的调用了,以实现项目的需求。
void Test() {
EmployeeTable employeeDAL = new EmployeeTable();
SearchConditionCollection filter = new SearchConditionCollection(); // 查询条件生成器
// 保存一个员工
EmployeeInfo employee = new EmployeeInfo();
employee.Name = " wfyfngu " ;
employee.DepartmentID = 4 ;
employeeDAL.Save(employee);
// 获取ID为1的员工
EmployeeInfo info = employeeDAL.GetByPrimaryKey( 1 );
// 查询所有员工
IList < EmployeeInfo > all = employeeDAL.GetAll();
// 分页查询
int itemCount;
IList < EmployeeInfo > pagedSource = employeeDAL.Search( null , 10 , 1 , out itemCount);
// 修改ID为1的员工的名字
employeeDAL.ChangeName( 1 , " wfyfngu " );
// 考虑到项目分层,业务逻辑层应该对数据库字段一无所知
// 所以,下面演示的方法仅仅出于演示目的,将字段名硬编码到方法中
// 删除ID为 1 2 5 7 的用户
filter.Add( new SearchCondition(
" user_id " ,
new ColumnComparison(SqlOperator.In, 1 , 2 , 5 , 7 )
));
employeeDAL.Delete(filter);
// 查询名字以wfy开头的员工,并分页
filter.Clear();
filter.Add( new SearchCondition(
" name " ,
new ColumnComparison(SqlOperator.StartWith, " wfy " )
));
IList < EmployeeInfo > result = employeeDAL.Search(filter, 10 , 1 , out itemCount);
}
}
其它功能,如简单的联表查询,视图查询等不一一列举。
附件说明:附件为本人编写的ORM替代框架,针对MySql编写,由于Cache功能涉及到另一个类库,所以在附件中去除了,需要的可以自己加入。
几个主要类源码:
框架下载地址:http://files.cnblogs.com/wfyfngu/SqlUtility.zip