ServiceStack.OrmLite

谈谈我的入门级实体框架Loogn.OrmLite

 

每次看到有新的ORM的时候,我总会留意一下,因为自己也写过一个这样的框架,人总是有比较之心的。我可能会down下来跑一跑,也可能不会这么做,这个取决于跑起来的难易程度。我是很懒的,有XML配置或其他稍微不直观的设置的,我总是懒得看。每当笔者谈论自己的ORM的时候,总会拿EF和Dapper说事儿,EF算官方的吧,Dapper则以效率著称。但是我很奇怪为什么ServiceStack.OrmLite这么NB的一个ORM却鲜为人提。我真想为它说一句话:.net的ORM框架中有一个非常优秀的成员叫ServiceStack.OrmLite !

我知道ServiceStack.OrmLite已是好几年前的事了。初次见面,甚是欢喜,以为找到了可以长久使用的ORM,喜欢它那简洁的API和超高的效率。在我打算爱上它的时候,发现了一个令我很不爽的地方:它的方法重载太多,其中有几个VS的智能提示区分不出来是哪个重载了,而这个方法的参数正好是需要提示的Lambda表达式,这一点一直使我耿耿于怀,没用上它。Loogn.OrmLite的名称和API都参考了它。

我写过好多版本的数据访问组件,感觉从毕业了就一直在写,当然,都是很简单的代码,包括现在这个OrmLite,我感觉自己写不出什么高深的代码。刚毕业的学生,如果会if else等C#基础,会简单的封装继承多态,就可以看懂。个人的ORM,风格上很大一部分受作者主观意识和遇境的影响,这都是很正常的,自己喜欢就好。比如我的ORM开始只支持MSSql,因为我到那个时候为止只用过mssql,后来一家公司要用MySql,于是花了两个小时让它支持mysql,前段时间又感觉sqlite这样一个本地数据库还是挺常用的,又花了一个小时让它支持sqlite。我一个朋友hubro也写了一个叫CRL的ORM,他那里面支持了mongodb,理由是这样就可以统一访问了。但我就不会支持(我和ServiceStack一样,是用扩展方法,没有自己的一层抽象,所以也实现不了,哈哈),因为我感觉mongodb的C#客户端封装的已经不错了,顶多在项目里面写个帮助类就可以到处跑了,我以前用mongodb就是这么干的。所以,个人的ORM都有自己的风格。

***********************************************************************

我先把效率测试结果贴出来,让大家有个底儿,让大家知道入门级的东西的效率也是不错的,然后接着叙:

注:测试代码源自Chloe.ORM ,有现成东西我习惯性会借用。还要谢谢Chloe.ORM的作者,就是在用作者的效率测试程序后,决定把自己的mapping改进了,中间还闹了笑话,哈哈!

注:记得园子里还有个CYQ.Data,也想一并测试了,但是得到MDataTable对象后,调用ToList的时候有点问题,Guid类型和String类型两个字段没赋值成功,后来好像还报了个类型转换错误,就没跑起来,我是在nuget里下载的引用(作者看到可亲测一下,也许是我哪里没搞好)

注:源码以及测试代码

  

1、Mapping count:5000000 表示一次查询出5000000条记录,测试mapping效率。可以看出效率基本差不多,ChloeSql和ServiceStack突出了一点,CRL最慢的原因是实体类有继承基类,大家知道,实例化对象的时候所有父类对象都必须实例化。

2、Query count :20000,Limit 10 表示查询20000次,每次查询10条记录。Dapper和ServiceStack的效率是超级棒的,最棒的是Loogn的(不太会吹NB,只能吹到这个程度了)

3、SingleContextQuery count:20000,Limit 10 表示在一个上下文中查询20000次,每次查询10条记录。Dapper和ServiceStack的效率还是超级棒的,最棒的还是Loogn的(刚开始学吹NB,还不熟练)

***********************************************************************

好我不吹牛逼,吹牛逼不是我的强项,我继续说相关的东西。

从上面的查询测试结果来看,Loogn.OrmLite是非常快的。为什么会这么快呢,就是因为它代码简单。都说自己的dll小,而Loogn.OrmLite.dll只有70多kb,是Dapper.dll的1/2,其他的可自行比较。当然功能也很简单,比如EF、Chloe.NET、CRL、ServiceStack都支持lambda表达式查询,我的就不支持。我承认Expression是一个非常好的特性,但是本人水平有限再加上很懒,一直不想涉足这块,简单的查询还好解析,复杂的查询不太好解析,或者调用起来很别扭,我不喜欢只支持一半的东西(当然,这都是自己安慰自己的理由,说白了还是能力不够),所以我以后也不打算支持。

他们的好像都封装了连接查询,而我的只是用sql语句来实现。关于连接查询返回多表数据如何接收的问题,EF和Chloe.NET好像都是用的匿名对象,这种返回值写起来很优雅,但是如果把返回值再传递一下(比如传递给另一个方法),智能提示就用不上了。CRL的好像是有一个主实体类,连接查询的其他附加字段通过这个主实体类的一个字典来保存,为了获取方便且在同一层级,还贴心地提供一个以string为参数的索引器来取值(比如user.exts["name"] 可以写成 user["name"]),这种方法以前我有用过,感觉还不错,但也不太喜欢。而Loogn.OrmLite根本没有顾及这些,只能一个查询映射到一个类,可以给这个类添加冗余属性来接收连接查询的他表字段,但是要加[OrmLiteField(Ignore = true)]特性。Loogn.OrmLite也可以返回dynamic或List<dynamic>类型,但实际开发中我基本没用过,动态类型的返回值在写demo或数据迁移的时候很方便,不用定义实体类了!其实在开发中,我已经很少用表连接了,要取多表数据怎么办呢?

第一种是可缓存的:比如新闻表有TypeID,另外还有个新闻类型表,在显示新闻的时候需要显示新闻类型的名称。这种情况的特点是另一个表的数据不常变动且很少,这里就可以把新闻类型表的数据缓存起来,在内存中操作,当然要处理好缓存过期的情况。

第二种是可冗余的:比如收藏文章,可以把文章标题也冗余的存储到收藏表里。

第三种是可id in 查询的:这种情况不适合查询3张表以上的,而且最好是id关联的,查出主表,获取ids,用 in 查询另一张表,然后再通过id关联,这些集合操作用lambda是很容易实现的,Loogn.OrmLite里有提供SelectByIds这样的方法,所以我比较常用。

可能还有其他情况的处理方法,如果没一个好的方法,直接用连接查询也没什么!

Mapping部分我的应该是最容易理解的了(在达到这个效率的前提下)。一般为了高效映射,作者都会运用传说中的黑暗魔法--IL。特别是Dapper,运用的很巧妙(Chloe.ORM应该借鉴了Dapper)。但是做为入门级框架写不出那样的代码。后来想想,数据库字段的类型也就那几种,于是就笨手笨脚的写了20多个强类型委托访问器,摘录基类和一对访问器如下:

public abstract class Accessor

{
    public void Set(TObject obj, object value)
    {
        if (value == null || value is DBNull)
        {
            return;
        }
        DoSet(obj, value);
    }
 
    public object Get(TObject obj)
    {
        return DoGet(obj);
    }
 
    protected abstract void DoSet(TObject obj, object value);
    protected abstract object DoGet(TObject obj);
 
}
 
 
public class IntAccessor : Accessor
{
    Action<TObject, int> setter;
    Func<TObject, int> getter;
    public IntAccessor(PropertyInfo prop)
    {
        setter = (Action<TObject, int>)Delegate.CreateDelegate(typeof(Action<TObject, int>), null, prop.GetSetMethod(true));
        getter = (Func<TObject, int>)Delegate.CreateDelegate(typeof(Func<TObject, int>), null, prop.GetGetMethod(true));
    }
    protected override void DoSet(TObject obj, object value)
    {
        setter(obj, (int)value);
    }
    protected override object DoGet(TObject obj)
    {
        return getter(obj);
    }
}
 
public class IntNullableAccessor : Accessor
{
    Action<TObject, int?> setter;
    Func<TObject, int?> getter;
    public IntNullableAccessor(PropertyInfo prop)
    {
        setter = (Action<TObject, int?>)Delegate.CreateDelegate(typeof(Action<TObject, int?>), null, prop.GetSetMethod(true));
        getter = (Func<TObject, int?>)Delegate.CreateDelegate(typeof(Func<TObject, int?>), null, prop.GetGetMethod(true));
    }
    protected override void DoSet(TObject obj, object value)
    {
        setter(obj, (int)value);
    }
    protected override object DoGet(TObject obj)
    {
        return getter(obj);
    }
}

其实就是一个多态的运用,理解起来还是很简单的,倒是[复制][粘贴][修改]费了不少时间。。。。。。

我基本没有用设计模式。检测这个有一个简单有效的方法,打开源码,随便找几个方法,按几次F12,看能不能都找到具体实现就知道了。用设计模式一般会基于接口、抽象类编程,这是一种非常好的编程方法,但是从一个初学者来说,或者像我这样直脑子的人来说,F12找不到具体实现总是感到很迷茫。我在支持mysql和sqlite的时候,完全是用if else判断来区分不同的代码逻辑的,比如一些语法不同的地方。这样的代码很挫,比如再支持一个Oracle数据库,我只能在每个这样的判断下面写更多的判断(所以新手要引以为戒)。目前这样的代码工作还算良好,等我水平达到了说不定会重构一下。

整篇下来,好像也没介绍多少关于我自己的框架,我的本意正是如此。一个原因是它功能简单,实在不知道说什么;另一个原因是我感觉使用个人框架一定要谨慎,别人写的东西只有非常了解才能运用自如,避免缺陷和误用功能。关于推荐,虽然我可能会一直用自己的,但还是首推EF。EF功能强大,上手极快,知名度高,语法优美,效率也不是什么大问题,我相信好多个人ORM也借鉴了EF。ServiceStack那个因为智能提示让我耿耿于怀,也不敢向大家推荐了,有兴趣的可自行把玩。

ServiceStack.OrmLite的更多相关文章

  1. ServiceStack.OrmLite中的一些"陷阱"(2)

    注:此系列不是说ServiceStack.OrmLite的多个陷阱,这仅仅个人认为是某一个陷阱(毕竟我踩坑了)而引发的思考. 前文说到了项目需要使用两种不同的数据库语言,虽说前文问题已基本解决了,但是 ...

  2. ServiceStack.OrmLite中的一些"陷阱"(1)

    使用过ServiceStack.Ormlite的人都应该知道,其作为一个轻量级的ORM,使用的便捷度非常高,用起来就一个字:爽!而支撑其便捷度的,是库内大量地使用了扩展方法及静态变量. 首先先从源头入 ...

  3. ServiceStack.OrmLite 学习笔记7-复杂点的使用1

    复杂点的使用1 先看看这2个类 class Customer { public int Id { get; set; } ... } class CustomerAddress { public in ...

  4. ServiceStack.OrmLite 笔记2 -增

    ServiceStack.OrmLite 笔记2 这篇主要介绍 增加 db.Insert(new Employee { Id = 1, Name = "Employee 1" }) ...

  5. ServiceStack.OrmLite 笔记

    ServiceStack.OrmLite 笔记1 ServiceStack.OrmLite 这个东东就是个orm框架,可以实现类似ef的效果.具体的就不这里班门弄斧了. 支持 SqlServerDia ...

  6. ServiceStack.OrmLite 调用存储过程

    最近在做关于ServiceStack.OrmLite调用存储过程时,有问题.发现ServiceStack.OrmLite不能调用存储过程,或者说不能实现我想要的需求.在做分页查询时,我需要传入参数传出 ...

  7. ServiceStack.OrmLite T4模板使用记录

    前言 最近研究了下ServiceStack.OrmLite,文档中也提到了使用T4模板对数据库中已经有了表进行实体的映射,这里也顺便记录下使用的步骤和情况. 开始使用 引用T4模板 首先我们创建一个工 ...

  8. ServiceStack.OrmLite 入门(一)

    软件环境: Win7 x64 SP1 SQL Server 2008r2 Visual Studio 2017 Professional 目标:取出示例数据库 ReportServer 的表 Role ...

  9. ServiceStack.OrmLite破解

    在 ServiceStack.OrmLite下的 OrmLiteConfigExtensions 第199行把这句注释掉就可以了 //LicenseUtils.AssertValidUsage(Lic ...

随机推荐

  1. max Sum(简单动态规划)

    http://acm.hdu.edu.cn/showproblem.php?pid=1003 / 给组测试数据 1 7 2 3 -4 -5 6 7 8 一个关键问题 : 什么时候将开始位置重新赋值 即 ...

  2. lightoj 1300 边双联通分量+交叉染色求奇圈

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...

  3. python 解析 配置文件

    资料: https://docs.python.org/3/library/configparser.html 环境 python 3.4.4 RawConfigParser方式 example.cf ...

  4. jEdit应用指南【基础篇】

    jEdit是Java编写,强大,易用的程序员文本编辑器 jEdit是一个成熟的,设计优秀的程序员文本编辑器,已经有了7年的开发历史.在功能和易用性方面压倒许多昂贵的开发工具时,jEdit在GNU公用许 ...

  5. mysql 更新有外键约束的字段

    给一个表的字段更新,发现 这个字段是外键,刚开始用了笨 的方法,取消外键,修改后,在添加, 网上百度了. 这样设置 先 关闭外键约束 SET FOREIGN_KEY_CHECKS=0; 执行完了 打开 ...

  6. Effect of Switchovers, Failovers, and Control File Creation on Backups

    对dataguard 官方文档里面的这句话不理解,是否能给出一个样例说明: 10.2.0.5的版本号 Effect of Switchovers, Failovers, and Control Fil ...

  7. Java之多线程断点下载的实现

    RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操 ...

  8. MYSQL 体系结构图-LRU FREELIST FLUSH LIST

  9. GCOV 使用用例

      1.GCOV查看arm-linux代码覆盖率 一.           关于gcov工具 gcov伴随gcc 发布.gcc编译加入-fprofile-arcs -ftest-coverage 参数 ...

  10. 关于 iOS socket 都在这里了

    socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程 ...