提起PDF.NET,相信不少第一次听见这个名字或者没有了解过这套框架的读者都会认为这必然是一套与PDF操作相关的框架组件,以正常的思维,您根本无法想象到这竟然是一套数据库操作框架。PDF.NET的全称是"PWMIS Data Develop Framework",它是由“深蓝医生”开发的一套数据库操作框架,致力于提供"代码的精简,开发、维护的简单与追求极致的运行效率"的开发方式,其官方网站为:"http://www.pwmis.com/sqlmap/",目前这套框架已经全面开源,代码托管为:"http://pwmis.codeplex.com/"。
虽然PDF.NET诞生已久,到现在也有五六个年头,也正如众多开源项目/框架一样,PDF.NET的知名度没有Dapper、PetaPoco之流的轻型ORM有名,更没有作为微软官方推荐的Entity FrameWork知名。因此,除了其作者的博客,鲜有关于它的文章以及介绍(当然,这更与我们绝大多数人只想着索取不考虑贡献的思维有关了),这对于初学者来说并不是好事,由于资料的缺乏(或是写作不合口味)造成了上手困难,失去对框架的信心。因此,本篇也正如题目所说的那样,希望通过介绍PDF.NET最初等的功能,以一种愉快的方式带领希望使用此框架“干点什么”的读者入门。
废话不多说,正式进入到本文的环节,在本文中,我们将讲解:
1、如何下载和获得相关组件。
2、实体模型的写法以及注意事项。
3、OQL是什么?怎么用?需要注意些什么?
相关Demo,可以点击这里下载。
一、如何获得相关组件
“巧妇难为无米之炊”,要使用PDF.NET开发程序,我们必须先获得该组件。
获取相关组件的方式有以下几种:
(1)、通过访问CodePlex代码托管网站获取源码来编译。
(2)、通过NuGet可视化界面获取(由“独行族妖侠”——玄离 上传)
(3)、可以通过程序包控制台执行:“Install-Package PDF.NET”获得(还是楼上这位里世界的朋友上传)
至此,我们也就获得了PDF.NET相关组件了。
二、实体模型的写法以及注意事项
实体模型(Entity)可谓是所有ORM必有的东西了,PDF.NET也不例外,但由于PDF.NET采用的是一种“无反射”的实体映射模式,因此它的实体写法也与其他基于Emit和ExpressionTree有一定的区别,我们还是先上一个Demo再作分析。
namespace MvcApplication1.Models { using PWMIS.DataMap.Entity; public class Person : EntityBase { public Person() { TableName = "Person"; PrimaryKeys.Add("ID"); IdentityName = "ID"; } public int ID { get { return getProperty<int>("ID"); } set { setProperty("ID", value); } } public string Name { get { return getProperty<string>("Name"); } set { setProperty("Name", value); } } public string Voice { get { return getProperty<string>("Voice"); } set { setProperty("Voice", value); } } public string Sex { get { return getProperty<string>("Sex"); } set { setProperty("Sex", value); } } } }
由代码中我们也可以看出以下两个值得关注的地方:
(1)、表名、主键、自增等配置需要在构造函数中设置。
(2)、属性的Get、Set属性需要使用getProPerty、setProperty方法来进行取值和设置,不能单纯的定义get、set。
这种特殊的写法,也与它的“无反射”有关,代码用没有一处是使用到Attribute,属性的获取/设置值也不采用GetValue、SetValue或更高级的反射相关技术来实现,当然咯,具体实现各位读者有兴趣的话可以参阅源代码,只是想单纯使用的话可以不用理会。
三、OQL是什么?怎么用?注意什么?
正如EntityFrameWork有ESQL、NHibernate有HSQL一样,PDF.NET也有其自身的表达式,那便是OQL。
同样的多说无谓,我们直接上一个Demo代码并根据代码来讲解:
namespace MvcApplication1.Data { using Models; using PWMIS.DataMap.Entity; using PWMIS.DataProvider.Data; using System.Collections.Generic; public class PersonData { private AdoHelper GetAdoHelper() { return AdoHelper.CreateHelper("myConn"); } public IList<Person> GetPersonList(string name, string sex) { var model = new Person(); var oql = OQL.From(model).Select("*").Where(x => { var cmp = x.Property(model.ID) > -1; if (false == string.IsNullOrWhiteSpace(name)) cmp = cmp & x.Property(model.Name) == name; if (false == string.IsNullOrWhiteSpace(sex)) cmp = cmp & x.Property(model.Sex) == sex; return cmp; }).END; return EntityQuery<Person>.QueryList(oql, this.GetAdoHelper()); } public bool DeleteByID(int id) { var model = new Person() { }; var oql = OQL.From(model).Delete().Where(x => { return x.Property(model.ID) == id; }).END; return EntityQuery<Person>.ExecuteOql(oql, this.GetAdoHelper()) > 0; } public bool Update(Person model) { var oql = OQL.From(model).Update(model.Name, model.Sex, model.Voice).END; return EntityQuery<Person>.ExecuteOql(oql, this.GetAdoHelper()) > 0; } } }
绝大部分的操作各位读者都可以通过读者直接得出答案,这里有以下几个需要重点讲解的:
(1)、使用OQL之前需要先实例化一个类,并以这个类来传入改类中构造函数所的相关配置等信息。
(2)、OQL的Where条件,事实上,我们经常会接触到根据上下文来动态的决定条件的个数并进行Where条件的动态拼装,OQL这里提供的动态拼接方式是使用一个委托的方式来实现(匿不匿名随意)。
(3)、细心的读者还会发现我在"GetPersonList"的匿名委托中做了个"ID>-1"这种"1=1"的事情,这是一个故意的步骤,由于OQLCompare(也就是那个Where匿名委托的类型)做了"&"操作符重载,每次执行"&"操作的时候都是产生新的对象(类似与Struct),而有趣的是PDF.NET对OQLCompare有跟踪功能,如果实例化cmp的时候直接new出一个对象,到return的时候PDF.NET将会抛出Exception。
(4)、如果Web.Config中。ConnectionString只有一个链接字串,则PDF.NET是默认采用此链接方式,代码中也可以省略"GetAdoHelper",直接使用ExecuteOql、QuerList等重载来执行,我在此使用了显式的方式指明ADOHelper目的就是为了万一有多个数据集链接字串的情况。
大概就这么多了,更多的还请读者自行根据实际情况进行相应的处理。
最后的结果,我给个有趣的图出来大家瞅瞅。
PDF.NET的操作风格或许与各位读者使用的ORM有较大区别,不少地方还似乎不是特别顺手,但是由于PDF.NET已经全面开源,各位读者也可以自由的参与到其中进行开发,把不喜欢的地方改掉,把不顺手的使用方式也改掉,把喜欢的特性加进去,一切都处决于您的想法。