ServiceStack.OrmLite
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的更多相关文章
- ServiceStack.OrmLite中的一些"陷阱"(2)
注:此系列不是说ServiceStack.OrmLite的多个陷阱,这仅仅个人认为是某一个陷阱(毕竟我踩坑了)而引发的思考. 前文说到了项目需要使用两种不同的数据库语言,虽说前文问题已基本解决了,但是 ...
- ServiceStack.OrmLite中的一些"陷阱"(1)
使用过ServiceStack.Ormlite的人都应该知道,其作为一个轻量级的ORM,使用的便捷度非常高,用起来就一个字:爽!而支撑其便捷度的,是库内大量地使用了扩展方法及静态变量. 首先先从源头入 ...
- ServiceStack.OrmLite 学习笔记7-复杂点的使用1
复杂点的使用1 先看看这2个类 class Customer { public int Id { get; set; } ... } class CustomerAddress { public in ...
- ServiceStack.OrmLite 笔记2 -增
ServiceStack.OrmLite 笔记2 这篇主要介绍 增加 db.Insert(new Employee { Id = 1, Name = "Employee 1" }) ...
- ServiceStack.OrmLite 笔记
ServiceStack.OrmLite 笔记1 ServiceStack.OrmLite 这个东东就是个orm框架,可以实现类似ef的效果.具体的就不这里班门弄斧了. 支持 SqlServerDia ...
- ServiceStack.OrmLite 调用存储过程
最近在做关于ServiceStack.OrmLite调用存储过程时,有问题.发现ServiceStack.OrmLite不能调用存储过程,或者说不能实现我想要的需求.在做分页查询时,我需要传入参数传出 ...
- ServiceStack.OrmLite T4模板使用记录
前言 最近研究了下ServiceStack.OrmLite,文档中也提到了使用T4模板对数据库中已经有了表进行实体的映射,这里也顺便记录下使用的步骤和情况. 开始使用 引用T4模板 首先我们创建一个工 ...
- ServiceStack.OrmLite 入门(一)
软件环境: Win7 x64 SP1 SQL Server 2008r2 Visual Studio 2017 Professional 目标:取出示例数据库 ReportServer 的表 Role ...
- ServiceStack.OrmLite破解
在 ServiceStack.OrmLite下的 OrmLiteConfigExtensions 第199行把这句注释掉就可以了 //LicenseUtils.AssertValidUsage(Lic ...
随机推荐
- First Record
今天我在博客园安家了! R Python Scala hadoop Spark MachineLearning
- B - Dungeon Master
题目大意: 地牢大师(感觉像是一款游戏啊.......) 你被困在一个3D的地牢里面,并且需要发现最快的出去的路,这个地牢由很多小立方体组成,有的是空的可以走,有的被岩石填充了不可以走,移动一 ...
- 11th day
今天MySQL数据库的基本知识就学完了,明天开始做小项目什么的,有点小激动啊... <?php // 定义$sql语句执行函数 function my_query($sql){ $result ...
- Android RelativeLayout 布局android:layout_centerHorizontal="true"注意
特别注意,如果要是 android:layout_alignTop="@id/bind_decode_item_layout" android:layout_centerHoriz ...
- 账户管理命令 useradd、groupadd
内容提要: 1. 掌握用户的 增/删/改 命令 2. 掌握组的 增/删/改 命令 组管理 1)groupadd groupadd 用于添加组账号.格式如下: groupadd [-g GID] GRO ...
- [转]Vim 复制粘帖格式错乱问题的解决办法
有时候,复制文本(尤其是代码)到 Vim,会出现格式错乱的问题.看样子,应该是自动缩进惹得祸.本文不去深究原因,直接给出解决方法. 1. paste 模式 运行如下命令,进入 paste 模式: :s ...
- 2015 UESTC Winter Training #10【Northeastern Europe 2009】
2015 UESTC Winter Training #10 Northeastern Europe 2009 最近集训都不在状态啊,嘛,上午一直在练车,比赛时也是刚吃过午饭,状态不好也难免,下次比赛 ...
- myeclipse跟eclipse中使用github做版本控制工具
今天早上花了一上午的时间,了解了在myeclipse跟eclipse中使用github. 好吧 说说怎么做的,让大伙少走一点路,我就简单描述下,需要软件的私信我 第一:下载git 第二:靠谱.但是pu ...
- Hibernate HQL查询:
Hibernate HQL查询:Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Lanaguage)查询提供了更加丰富的和灵活的查 ...
- Java编程思想-泛型-泛型方法
代码示例如下: package generics; //: generics/GenericMethods.java public class GenericMethods<A> { // ...