谈谈我的入门级实体框架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那个因为智能提示让我耿耿于怀,也不敢向大家推荐了,有兴趣的可自行把玩。

时间: 2024-08-12 17:33:07

谈谈我的入门级实体框架Loogn.OrmLite的相关文章

011.EF实体框架(入门)

1>ASP.NET MVC开发中模型的实现方法 模型的实现方法 两种方法1手动2自动(工具 EF)1.1手动创建模型(写好模型元数据)[练习过了 项目!] 前提条件:先手动创建数据库和表 (模型:实体类,实体访问类,Sqlhelper) (Sqlhelper使用ADO.NET传统方法实现) 1.2使用EF(Entity Framework:实体框架)创建模型 2>EF的概念2.1什么是EF***EF是 实体框架 (Entity Framework)的简称,***EF 可以用来定义模型类并操作数

实体框架

实体框架的使用分为Model First,Code First(代码生成模型),Database First.Model First和Database First会使用实体设计器(edmx文件)来创建实体数据模型. DbContext所使用的连接字符串如果是常规连接字符串在使用Code First,如果使用的是特殊的实体框架连接字符串,则使用Database First或Model First. Database First: 从现有数据库构建edmx文件,然后edmx会生成DbContext和

实体框架高级应用之动态过滤 EntityFramework DynamicFilters

实体框架高级应用之动态过滤 EntityFramework DynamicFilters 我们开门见山,直奔主题. 一.EntityFramework DynamicFilters 是什么,它能做什么? EntityFramework DynamicFilters是一个开源项目.你可以到这里去下载它的源码.顾名思义,它为我们做的事,就是帮我们动态过滤数据.为了照顾初学者,我们从头道来. 1.何为数据过滤? 数据过滤说简单点,就是去掉我们不想要的数据.SQL语句中的where从句,Linq中的wh

实体框架6.0(Recipes)翻译系列 1 -----第一章 开始使用实体框架1

微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF版本更新太快,没人愿意去花时间翻译国外关于EF的书籍.使用Entity Framework开发已经有3年多了,但用得很肤浅,最近想深入学习,只好找来英文书<Entity Framework 6 Recipes>慢慢啃.首先需要说明的是,我英文不好,只是为了学习EF.把学习的过程写成博客,一是督促自

在快速自定义的NopCommerce中使用实体框架(EF)代码优先迁移

我看到很多nopCommerce论坛的用户问他们如何使用Entity Framework(EF)代码优先迁移来自定义nopCommerce,添加新的字段和entites核心.我实际上在做nopCommerce定制项目时使用了很多EF Migrations,我必须说它在开发中有很大帮助. 今天,我将与大家分享如何在nopCommerce项目中做到这一点!我将使用nopCommerce 3.20作为例子,但你可以很容易地应用这个概念到其他的vesions! 原文链接:http://www.nopcn

C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)

译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 and .NET Core 1.0>.水平有限,各位阅读时仔细分辨,唯望莫误人子弟. 附英文版原文:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core ------------------------------- 本章内容 En

《Entity Framework 6 Recipes》翻译系列(2) -----第一章 开始使用实体框架之使用介绍 (转)

Visual Studio 我们在Windows平台上开发应用程序使用的工具主要是Visual Studio.这个集成开发环境已经演化了很多年,从一个简单的C++编辑器和编译器到一个高度集成.支持软件开发整个生命周期的多语言环境. Visual Studio以及它发布的工具和服务提供了:设计.开发.单元测试.调试.软件配置和管理.构建管理和持续集成等等.很少有开发人员因为还没有使用它而担心(注:作者应该是表达不用担心VS的能力),Visual Studio是一个完整的工具集.Visual Stu

《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述 (转)

微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF版本更新太快,没人愿意去花时间翻译国外关于EF的书籍.使用Entity Framework开发已经有3年多了,但用得很肤浅,最近想深入学习,只好找来英文书<Entity Framework 6 Recipes>第二版,慢慢啃.首先需要说明的是,我英文不好,只是为了学习EF.把学习的过程写成博客,一

EF实体框架之CodeFirst一

对于SQL Server.MySql.Oracle等这些传统的数据库,基本都是关系型数据库,都是体现实体与实体之间的联系,在以前开发时,可能先根据需求设计数据库,然后在写Model和业务逻辑,对于Model类基本都是和表的字段对应着,而表中存的每条记录又和类的实例对象对应着,有了这个对照关系,就是能不能只在一边设计,在数据库设计表或在VS中设计Model,然后直接生成另一边,这样就省了好多时间成本.于是有了ORM,Object Relation Mapping,对象关系映射.既然可以根据Mode