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 ...
随机推荐
- max Sum(简单动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=1003 / 给组测试数据 1 7 2 3 -4 -5 6 7 8 一个关键问题 : 什么时候将开始位置重新赋值 即 ...
- lightoj 1300 边双联通分量+交叉染色求奇圈
题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...
- python 解析 配置文件
资料: https://docs.python.org/3/library/configparser.html 环境 python 3.4.4 RawConfigParser方式 example.cf ...
- jEdit应用指南【基础篇】
jEdit是Java编写,强大,易用的程序员文本编辑器 jEdit是一个成熟的,设计优秀的程序员文本编辑器,已经有了7年的开发历史.在功能和易用性方面压倒许多昂贵的开发工具时,jEdit在GNU公用许 ...
- mysql 更新有外键约束的字段
给一个表的字段更新,发现 这个字段是外键,刚开始用了笨 的方法,取消外键,修改后,在添加, 网上百度了. 这样设置 先 关闭外键约束 SET FOREIGN_KEY_CHECKS=0; 执行完了 打开 ...
- Effect of Switchovers, Failovers, and Control File Creation on Backups
对dataguard 官方文档里面的这句话不理解,是否能给出一个样例说明: 10.2.0.5的版本号 Effect of Switchovers, Failovers, and Control Fil ...
- Java之多线程断点下载的实现
RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操 ...
- MYSQL 体系结构图-LRU FREELIST FLUSH LIST
- GCOV 使用用例
1.GCOV查看arm-linux代码覆盖率 一. 关于gcov工具 gcov伴随gcc 发布.gcc编译加入-fprofile-arcs -ftest-coverage 参数 ...
- 关于 iOS socket 都在这里了
socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程 ...