不要EntityFramework,不要NHibernate,打造自己的ORM(二)

我的ORM,暂时命名为LinFramwork吧,有如下特点:

一 不仅支持若干主流数据库SQL Server,Oracle等,基于我前面随笔里阐述的通用数据访问组建原理,只要提供相关数据库ADO.NET Provider,并实现SQL解析的接口,还可以支持新的数据库类型。同时,对于调用者完全"透明",即开发人员只需定义数据库连接字符串即可,无须象其他ORM那样,还要在配置文件里加上数据库类型的属性。对于Oracle,我直接集成了Oracle的ODP.NET的相关dll,使其免客户端安装。简而言之,假如把数据库从SQL Server切换到Oracle,把连接信息改改即可。
客户端配置文件

 <connectionStrings>
        <add name="MSSQL"  connectionString="Data Source=localhost\sqlexpress;
             Initial Catalog=Northwind;Integrated Security=True"/>
        <add name="Oracle" connectionString="Data Source=(DESCRIPTION =(ADDRESS_LIST=
             (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.116.128)(PORT = 1521)))(CONNECT_DATA =
             (SID = xe)(SERVER = DEDICATED)));User ID=sa;password=sa" />      
    </connectionStrings>

  客户端初始化实体对象上下文

            EntityContext sqlContext = new EntityContext(ConfigurationManager.ConnectionStrings["MSSQL"].ConnectionString);
            EntityContext oraleContext = new EntityContext(ConfigurationManager.ConnectionStrings["Oracle"].ConnectionString);


二 类似EF的Codefirst,只需简单的定义一个实体。

 public class Categories
    {
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
        public string Description { get; set; }

    }

 注意看实体的定义与一般ORM的区别,我看过很多人自己开发的ORM,均觉得实体定义太罗嗦了,或者NH那样搞一大堆xml定义实体,或者像EF那样必须继承一个实体基类,或者在实体的属性上加上一堆特性定义,诸如对应的数据库表名称,字段名称,是否主键,是否自增,字段类型等等(很多orm同时具备以上几点),而我这里的设计,就这么简单,可以什么特性都不加,也不用继承什么实体基类,更不用再搞一堆xml。 

三 提供泛型的统一CRUD接口。
这里摘取几个最常用的CURD方法作为示例

 EntityContext context = new EntityContext(ConfigurationManager.ConnectionStrings["Oracle"].ConnectionString);
            // 新增            
            context.Insert(new Product() { Categoryid = 1, CategoryName = "食品" });
            //查询            
            Product product =  context.GetEntityByKey<Product>(8);
            //修改             
            product.CategoryName ="xxxxx";
            context.Update(product);
            //删除          
            context.Delete(product);

  

四  新增记录时可以返回自增主键(同时支持 SQL Server 和Oracle,oracle需要建序列)

五 更新记录时可以只修改有改动的字段

         //修改            
        context.PreUpdate(product);
        product.CategoryName ="xxxxx";
            context.Update(product);

五 将查询结果转换为实体集合时使用Emit实现,达到最佳性能。

List<Product> products = context.Query<Product>("Categoryid=@Categoryid", 1);

六 只需定义简单实体,无需xml定义,无需代码生成,实体特性上无需加入元数据信息,达到使用最简单化。

七 查询条件参数化,简单明了(参看五的代码)。

八 事务支持

 try
            {
                context.BeginTransaction();
                context.Update(product);
                context.Delete(product);
                context.Commit();
            }
            catch (Exception ex)
            {
                context.Rollback();
            }

  

 九 支持扩展数据库支持,只需实现我的解析sql的接口和提供可以执行该sql的data provider即可。

 简单概括就是,配置一个数据库连接,并用该连接实例化一个ObjectContext对象,定义一个与数据库表对应的实体,实体定义无需添加任何特性,便可实现CRUD了,我自认为是最简单易用的ORM,当然我这个orm还有很多人性化的地方,我并没有细细道出,这里只是介绍个大概。各位网友还有什么更好的提议或者更多的想了解的细节,欢迎提出!

 

关于网友提到源码和试用的问题,我这里作一个补充说明 暂时提供dll下载,不开放源码,原因如下
1 框架目前来说完成不久,虽然主体功能都已经有了,但还需要实践检验。
2 由于是我个人业余时间写的,代码写的比较粗矿,日志跟踪,异常处理之类是基本没有的。。。
3 将来可能会在工作中使用。

当然也不排除一段时间,代码成熟以后,朋友们感兴趣的话,我发布源码。
使用方式很简单,下载dll,引用这两个dll就可以了。如果是oracle,连接字符串参考我的写法,另外需要拷贝
OraOps11w.dll,Oracle.DataAccess.dll,orannzsbb11.dll,oci.dll,ociw32.dll,oraocci11.dll,oraociei11.dll
至执行文件的同一个目录下,开发过程中就是debug目录。

 

至于如何使用问题,其实我上面已经有提及,使用非常简单,以sql server 为例,假设你已经建好表Product(ID,Name,CategoryID),ID是自增列,
那么项目中引入两个dll后,定义实体 Product :

public class Product
{
 public int ID {get;set;}
 public string Name {get;set;}
public int CategoryID {get;set;}

}

调用代码如下
 EntityContext  context = new EntityContext("数据库连接串");
 context.Insert(new Product(){Name="pppp", CategoryID=55});

 如果ID不是自增列,那么在实体在执行插入操作前需要赋值。 

 下载

posted on 2012-05-20 16:20  lindping  阅读(3602)  评论(37编辑  收藏  举报