.NET框架下ORM的一个轻量高效替代方案

从最初做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与上表各字段对应
现在我们需要为这个表写一个访问类,提供对数据库的增、删、改、查工作。
下面是实现以上功能的所有代码:

public   class  EmployeeTable : TableAccess < 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   class  EmployeeTable : TableAccess < EmployeeInfo >  {

    
//  修改员工名字
     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);
    }

}

 

最后就是对上面类各个方法的调用了,以实现项目的需求。

 

public   class  EmployeeTableTest {

    
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功能涉及到另一个类库,所以在附件中去除了,需要的可以自己加入。

 

几个主要类源码:

ReadonlyTableAccess<T>

TableAccess<T>

JoinTableAccess<T>

框架下载地址:http://files.cnblogs.com/wfyfngu/SqlUtility.zip

 

 

转载于:https://www.cnblogs.com/wfyfngu/archive/2010/01/27/1657762.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值