• ORM之殇,我们需要什么样的ORM框架?


    最近在研究ORM,究竟什么样的框架才是我们想要的

    开发框架的意义在于

    • 开发更标准,更统一,不会因为不同人写的代码不一样
    • 开发效率更高,无需重新造轮子,重复无用的代码,同时简化开发流程
    • 运行效率得到控制,程序稳定性得到提高

    把网上关注比较多的框架搜了搜,作了个列表

    1. Nhibernate
      来源于Java的Hibernate
      参考:http://www.cnblogs.com/ylwn817/articles/1963528.html
    2. Entity Framework
      微软本家框架,都比较熟悉
    3. iBATIS.NET
      apache开源项目
      参考:http://developer.51cto.com/art/200907/137796.htm
    4. Nbear
      博客园Teddy开发的项目
      参考:http://www.cnblogs.com/teddyma/archive/2006/11/07/553562.html
    5. Castle ActiveRecord
      ActiveRecord是Hibernate的一个延伸
      参考:http://terrylee.cnblogs.com/archive/2006/04/03/365762.html

    加再上其他人写的一些框架,包括自已写的,大差不差

    整理了一些常用的特性,对这些框架作一个评分

    1. 可编程性(语法支持) 我们希望不再用字符串的形式拼接SQL,并且能通过编译验证
    2. 容错性 可看作是上面扩充,不希望一个地方改了,其它地方没改,没任何提示,造成错误
    3. 开发效率 包括框架的配置,开发过程
    4. 关联查询支持度 关联查询是不可避免的
    5. 额外配置 是否需要额外配置和第三方工具支持,影响开发效率
    6. 缓存支持 能大大增强程序效率

    跟数据库打交道,最重要的功能当属查询了,查询做得好不好直接影响易用度,Lambda和Linq方式为首选

    下面是对这些框架的分析,没有仔细研究,可能不对,只代表个人意见,仅供参考

    Nhibernate

    新版Nhibernate增加了Lambda和Linq查询支持

    Join好像也能实现了

    var list1 = session.CreateCriteria<Product>()
        .Add(Restrictions.Eq("Discontinued", false))
        .Add(Restrictions.Eq("Category.Id", 2))
        .List<Product>();
    

    对缓存支持也有,有多种实现方式
    http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html

    只是一如既往需要配置XML映射

    Entity Framework

    在上述特性中,除了没有缓存,EF都比较完美,关且在最新版7中,强制了CodeFirst模式,是其它框架没有的(这样更符合业务开发模式)

    有的说EF太过庞大,用不好效率会有些问题,确实,特别是关联,写不好就弄出没效率的SQL语句,这也正是他可编程性太强的缘故,如果不是这么强,就不会这么写,会想想把结构好好设计设计

    由于太过于对象的概念,默认不支持批量更新/删除

    iBATIS.NET

    除了有基本的对象映射优点只剩灵活来描述了,所有操作都需要配置XML文件来表示

    ﹤select id="GetAllAccountsAsHashMapViaResultMap" 
                    resultMap="account-hashtable-result"﹥  
        select *  
        from Accounts  
        order by Account_ID  
    ﹤/select﹥ 

    好像还支持缓存

    ﹤select id="GetCachedAccountsViaResultMap" 
                resultMap="account-result" 
                cacheModel="account-cache" ﹥  
        select *  
        from Accounts  
        order by Account_ID  
    ﹤/select﹥ 
    

    这已经不属于面向对象,就是一个查询映射

    Nbear

    Nbear可以通过对象的方式自动映射对象关联,但不能直接关联查询
    条件查询,参数化,不太智能,好像好长时间没更新了,不知现在是怎么查

    LocalUser[] users = gateway.Select<LocalUser>(_Entity.LocalUser.Id > 5 | _Entity.LocalUser.LoginId == "teddy", _Entity.LocalUser.Id.Desc & _Entity.LocalUser.LoginId.Asc);
    

      

    可以使用配置的方式支持缓存,好像只能单个表

    <cacheConfig enable="true">
        <cachingTables>
          <add key="Northwind.Orders" value="5" />
        </cachingTables>
     </cacheConfig>
    

    除了表映射外,还支持视图,存储过程映射,(这个其实已经脱离面向对象的概念了,设计好的业务对象,对这基本没需求)
    对象定义是接口类型,不明白

    public interface IdentableEntity : IEntity
    
           {
    
               [PrimaryKey]
    
               int Id { get; set; }
    
               string Name { get; set; }
    
           }
    

      

    Castle ActiveRecord

    ActiveRecord延伸于hibernate,少不了一堆数据库配置

    也支持关联对象,通过属性定义

      [HasMany(typeof(Post), Table="posts", ColumnKey="post_blogid")]
    
        public IList Posts
    
        {
    
            get { return _posts; }
    
            set { _posts = value; }
    
        }

    查询方式为方法传参,比较原始,不知最新的没有引入Linq和Lambda
    http://terrylee.cnblogs.com/archive/2006/04/12/372823.html

    SimpleQuery query = new SimpleQuery(
                typeof(Post),typeof(int),
               @"select post.Id from Post post where post.Created between ? and ?",
                start,end
                );

    综合起来

      可编程性(语法支持) 容错性 开发效率 关联查询支持度 额外配置 缓存支持
    Nhibernate Linq&Lambda语法 映射需要配置XML 支持
    Entity Framework Linq&Lambda语法   不支持
    iBATIS.NET XML配置查询 支持
    Nbear 运算符重载 需要工具生成类 支持
    Castle ActiveRecord   支持

    查询

    在设计ORM框架时,来表示查询一般分几种情况

    • 实现linq&Lambda语法糖,借助.NET框架实现表达式解析
    • 自已写表达式,实现类似的效果(代价是要借助工具生成一堆代理类,好多个人开发的框架都有这种弊病)
    • 通过方法表示运算 如.BigThan("Number",">10") 这样太复杂,可编程性差,容错性低
    • 直接SQL 这种会造成可编程性和容错性低

    可以看出最好的方式当属Linq和Lambda了

    更新

    理想情况下,对象的哪个属性修改了,就更新到哪个数据库里,会有以下几种设计

    1. 在属性SET方法上做文章,以在值修改了知道是哪个属性被更改了,更新时按此进行判断
      代价:需要大批量修改SET方法或用模版生成(EF7好像已经解决这个问题了)
    2. 参过参数的形式赋值,缺点是不太智能,可编程性容错性不高
    3. 采用AOP消息代理拦截属性变动,这种效率太低,并且没法调试

    性能,缓存

    虽然现在很少看到WEB服务器CPU占用很高,但运行效率还是需要考虑,运行逻辑判断时间直接影响请求响应时间,在ORM框架

    这个时间多消耗在类型与数据映射,要减少响应时间,需要对映射行为进行优化,减少不必要的计算

    开发高效的应用程序少不了缓存的支持,数据不可能总是从数据库读取,也不总是非要进行关才才能获得数据

    缓存创建,过期处理,和查找效率也需要进行考虑,像Nhibernate和Nbear必须先进行配置才能缓存,简值不能忍

    CodeFirst Or DbFirst

    上面也提到,EF7强制了CodeFirst模式,开发观念要发生改变了,先业务后数据,数据是基于业务实现得来的,理想情况下

    有什么样的业务结构,就应该会有什么样的数据表结构,不应去管数据库是什么样的,由框架来处理就行了,比如自动映射,自动创建维护数据库

    那种写完对象结构还得再配个XML数据表映射文件的形为,得拖出去枪毙10分钟

    开发便捷性

    好多框架需要用工具生成一堆代理类,增加属性/字段了,再生成一遍,这样便捷性很低,就像一辆赛车开跑前先得预热10分钟,很让人着急

    泛类型问题:对数据进行操作时,有的必须带上泛类型,这样在开发时感觉带上了一个尾巴,很冗余,不方便

    多种数据库/多库支持

    多库支持不可避免,这意味着框架能按业务进行配置使用哪个库

    在框架设计时基本会考虑多种数据库支持,如果是多种数据库多库... 

    以上仅为个人观点,不对的地方请指证

  • 相关阅读:
    08月24日总结
    08月23日总结
    08月22日总结
    装饰器
    卢菲菲最强大脑记忆训练法全套教程 01
    LeetCode 704 二分查找
    LeetCode 1480 一维数组的动态和
    NIO 总结
    LeetCode 881 救生艇
    url的组成部分
  • 原文地址:https://www.cnblogs.com/hubro/p/4353305.html
Copyright © 2020-2023  润新知