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. php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...

  2. IFTT-意大利金融交易税

    港交所公告,IFTT目前适用于Prada股份及其4只权证,所有于今年3月1日或之后买入Prada的投资者均要缴付IFTT.就股份而言,IFTT税率为交易价值的0.22%(2014年1月1日起将降至0. ...

  3. Spring task任务调度详解

    spring内部有一个task是Spring自带的一个设定时间自动任务调度 task使用的时候很方便,但是他能做的东西不如quartz那么的多! 可以使用注解和配置两种方式,配置的方式如下 引入Spr ...

  4. 隐式intent

    使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其他程序的活动, 这里我们首先指定了Intent的action是Intent.ACTION_VIEW,这是一个Android系统内置的 ...

  5. scrollview中停止滚动的监听

    [补充]可以在主线程控制,特别注意 scrollView3.postDelayed(new Runnable() { @Override public void run() { scrollView3 ...

  6. 一起学android之怎样获取手机程序列表以及程序相关信息并启动指定程序 (26)

    效果图: 程序列表: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFpX3FpbmdfeHVfa29uZw==/font/5a6L5L2T/fonts ...

  7. [转] Maven镜像配置

    参考:许晓斌的<Maven实战> 镜像是为了提供更快的服务 如图:X就认为是Y的一个镜像. 编辑settings.xml配置中央仓库镜像: <settings> ... < ...

  8. Android四大图片缓存(Imageloader,Picasso,Glide,Fresco)原理、特性对比

    四大图片缓存基本信息 Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用. Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所 ...

  9. Command 命令模式

    简介 将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化.用于[行为请求者]与[行为实现者]解耦,可实现二者之间的松耦合,以便适应变化. 将一个请求封装为一个对象,从而使你可用不同 ...

  10. Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas

    Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas   1,Bitmap对象的获取 首先说一下Bitmap,Bitmap是Androi ...