【译】微型ORM:PetaPoco

PetaPoco是一款适用于.Net 和Mono的微小、快速、单文件的微型ORM。

PetaPoco有以下特色:

  • 微小,没有依赖项……单个的C#文件可以方便的添加到任何项目中。
  • 工作于严格的没有装饰的Poco类,和几乎全部加了特性的Poco类
  • Insert/Delete/Update/Save and IsNew 等帮助方法。
  • 分页支持:自动得到总行数和数据
  • 支持简单的事务
  • 更好的支持参数替换,包括从对象属性中抓取命名的参数。
  • 很好的性能,剔除了Linq,并通过Dynamic方法快速的为属性赋值
  • T4模板自动生成Poco类
  • 查询语言是Sql……不支持别扭的fluent或Linq语法(仁者见仁,智者见智)
  • 包含一个低耦合的Sql Builder类,让内联的Sql更容易书写
  • 为异常信息记录、值转换器安装和数据映射提供钩子。(Hooks for logging exceptions, installing value converters and mapping columns to properties without attributes.)
  • 兼容SQL Server, SQL Server CE, MySQL, PostgreSQL and Oracle。
  • 可以在.NET 3.5 或Mono 2.6或更高版本上运行
  • 在.NET 4.0 和Mono 2.8下支持dynamic
  • NUnit单元测试
  • 开源(Apache License)
  • 所有功能大约用了1500行代码

 

可以从这里获得PetaPoco:

  • NuGet - http://nuget.org/List/Packages/PetaPoco
  • GitHub - https://github.com/toptensoftware/petapoco

 

代码展示:

首先,定义一个Poco类:

// Represents a record in the "articles" table
public class article
{public long article_id { get; set; }public string title { get; set; }public DateTime date_created { get; set; }public bool draft { get; set; }public string content { get; set; }
}

接下来,创建一个PetaPoco.Database,来执行查询:

// Create a PetaPoco database object
var db=new PetaPoco.Database("connectionStringName");// Show all articles    
foreach (var a in db.Query<article>("SELECT * FROM articles"))
{Console.WriteLine("{0} - {1}", a.article_id, a.title);
}

得到一个scalar:

long count=db.ExecuteScalar<long>("SELECT Count(*) FROM articles");

得到一行记录:

var a = db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0", 123));

 

获取分页数据:

PetaPoco能够自动完成分页请求

var result=db.Page<article>(1, 20, // <-- page number and items per page"SELECT * FROM articles WHERE category=@0 ORDER BY date_posted DESC", "coolstuff");

你将会得到一个PagedFetch对象:

public class Page<T> where T:new()
{public long CurrentPage { get; set; }public long ItemsPerPage { get; set; }public long TotalPages { get; set; }public long TotalItems { get; set; }public List<T> Items { get; set; }
}

PetaPoco在背后为我们做了一下处理:

  1. 生成并执行一个查询,得到匹配的数据行数
  2. 修改原始的查询语句,使其只得到所有匹配数据的一个子集

你现在已经拥有了一个展示单页数据的一切东西和一个分页控制器,他们被封装在一个现成的小对象中。(You now have everything to display a page of data and a pager control all wrapped up in one handy little object!)

 

Query vs Fetch

Database 对象有两个获取数据的方法:Query 和Fetch。这两个方法非常相似,不同的是Fetch方法返回一个POCO类的List<>,而Query使用 yield return 迭代所有数据,这些数据并没有加载到内存中。

 

不带查询的命令

使用Execute 方法执行一个不带查询的命令:

db.Execute("DELETE FROM articles WHERE draft<>0");

 

Inserts、Updates 和 Deletes

PetaPoco提供了insert、update和delete操作的帮助。

在插入一条记录时,你需要指定插入的表名和主键:

// Create the article
var a=new article();
a.title="My new article";
a.content="PetaPoco was here";
a.date_created=DateTime.UtcNow;// Insert it
db.Insert("articles", "article_id", a);// by now a.article_id will have the id of the new article

更新记录也一样:

// Get a record
var a=db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0", 123);// Change it
a.content="PetaPoco was here again";// Save it
db.Update("articles", "article_id", a);

或者你可以传一个匿名类来更新一部分字段。下面的代码只更新article的title字段:

db.Update("articles", "article_id", new { title="New title" }, 123);

删除:

// Delete an article extracting the primary key from a record
db.Delete("articles", "article_id", a);// Or if you already have the ID elsewhere
db.Delete("articles", "article_id", null, 123);

 

修饰POCO类

在上面的例子中,必须指明表名和主键是很烦人的,你可以在你的Poco类中附加这些信息:

// Represents a record in the "articles" table
[PetaPoco.TableName("articles")]
[PetaPoco.PrimaryKey("article_id")]
public class article
{public long article_id { get; set; }public string title { get; set; }public DateTime date_created { get; set; }public bool draft { get; set; }public string content { get; set; }
}

简化后的insert、update、delete:

// Insert a record
var a=new article();
a.title="My new article";
a.content="PetaPoco was here";
a.date_created=DateTime.UtcNow;
db.Insert(a);// Update it
a.content="Blah blah";
db.Update(a);// Delete it
db.Delete(a);

delete和update的其它方式

// Delete an article
db.Delete<article>("WHERE article_id=@0", 123);// Update an article
db.Update<article>("SET title=@0 WHERE article_id=@1", "New Title", 123);

你还可以告诉POCO忽略某列

public class article
{[PetaPoco.Ignore]public long SomeCalculatedFieldPerhaps{ get; set; }
}

或许你喜欢一点更详细的描述。和自动映射所有列相比,你可以通过使用类和列的属性来指明哪些列需要映射。

// Represents a record in the "articles" table
[PetaPoco.TableName("articles")]
[PetaPoco.PrimaryKey("article_id")]
[PetaPoco.ExplicitColumns]
public class article
{[PetaPoco.Column]publiclong article_id { get; set;}[PetaPoco.Column]publicstring title { get; set;}[PetaPoco.Column]publicDateTime date_created { get; set;}[PetaPoco.Column]public bool draft { get; set;}[PetaPoco.Column]publicstring content { get; set;}
} 

它可以结合partial class 很好的工作,把需要绑定的字段放在一个.cs文件中,把计算得到的和别的有用的属性添加到分开的文件中,而不用去考虑DAL。

Hey!是不是已经有装饰POCO数据库的标准属性了呢?

好吧,PetaPoco仅支持少数几个,因为我不想引起混乱。

Hey!稍等……它们不是POCO对象了!

当然,它们打破了严格的POCO概念,但使用它们可以让POCO更容易工作。

T4 模板

Writing all those POCO objects can soon get tedious and error prone... so PetaPoco includes a T4 template that can automatically write classes for all the tables in your your SQL Server, SQL Server CE, MySQL, PostgreSQL or Oracle database.

Using the T4 template is pretty simple. The git repository includes three files (The NuGet package adds these to your project automatically in the folder \Models\Generated).

  • PetaPoco.Core.ttinclude - includes all the helper routines for reading the DB schema
  • PetaPoco.Generator.ttinclude - the actual template that defines what's generated
  • Database.tt - the template itself that includes various settings and includes the two other ttinclude files.

A typical Database.tt file looks like this:

<#@ include file="PetaPoco.Core.ttinclude" #>
<#
   
// Settings
   
ConnectionStringName="jab";
   
Namespace=ConnectionStringName;
   
DatabaseName=ConnectionStringName;
   
stringRepoName=DatabaseName+"DB";
    bool
GenerateOperations=true;

   
// Load tables
   
var tables =LoadTables();

#>
<#@ include file="PetaPoco.Generator.ttinclude" #>

To use the template:

  1. Add the three files to you C# project
  2. Make sure you have a connection string and provider name set in your app.config or web.config file
  3. Edit ConnectionStringName property in Records.tt (ie: change it from "jab" to the name of your connection string)
  4. Save Database.tt.

All going well Database.cs should be generated with POCO objects representing all the tables in your database. To get the project to build you'll also need to add PetaPoco.cs to your project and ensure it is set to compile (NuGet does this for you) .

The template is based on the SubSonic template. If you're familiar with its ActiveRecord templates you'll find PetaPoco's template very similar.

自动的Select语句

当使用PetaPoco时,大多数查询都以"SELECT * FROM table"开头。鉴于我们现在可以从POCO对象的attribute中得到表名,我们没有理由不自动生成Select语句。

如果你运行一个不以select开头的查询, PetaPoco会自动的将它加上:

// Get a record
var a=db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0",123);

可以简写:

// Get a record
var a=db.SingleOrDefault<article>("WHERE article_id=@0",123);

PetaPoco实际上并不生成"SELECT *",它更准确的得到要查询的列名。

IsNew 和Save 方法

有时你有一个POCO,你想要知道数据库中是否已经存在。因为我们有主键,我们所要做的检查是该属性被设置为别的值还是默认值。

检测是否为新增:

// Is this a new record 
if(db.IsNew(a))
{
   
// Yes it is...
}

和它相关联还有一个Save方法,它将根据判断的结果执行Insert或Update。

// Save a new or existing record
db
.Save(a);

事务

事务相当的简单:

using (var scope=db.Transaction)
{
   
// Do transacted updates here

   
// Commit
    scope
.Complete();
}

事务可以是嵌套的,因此你可以调用其它包含事务的方法,或者被包含在单个的事务中。当所有事务都执行完成了,事务将会提交,否则所有操作都将回滚。

注意:为了使用事务,所有操作都需要相同的PetaPoco Database对象实例。你很可能想到IOC容器中为在每一个http请求或每一个线程共享同一个实体,我喜欢用StructureMap。

Linq从哪儿实现?

没有任何支持。我在Subsonic中使用Linq很长时间,我发现自己下降到使用CodingHorror 来做这些事情,因为:

  •  不能用简单的Linq实现
  •  在.NET 下工作,但不支持Mono(尤其是Mono 2.6)
  • 低效。例如:Subsonic 中activerecord.SingleOrDefault(x=x.id==123)的效率比CodingHorror 低20倍。

 

Now that I've got CodingHorror all over the place it bugs me that half the code is Linq and half is SQL.

Also, I've realized that for me the most annoying thing about SQL directly in the code is not the fact that it's SQL but that it's nasty to format nicely and to build up those SQL strings.

So...

PetaPoco's SQL Builder

目前已经有很多构建SQL的API,以下是我的版本,它确实很基础!

我的目标是格式化SQL更简单,并且通过适当的参数替换达到防止SQL注入的作用。这不能保证SQL语法的正确,也不支持使用intellisense。

以下是非常基础的写法:

var id=123;
var a=db.Query<article>(PetaPoco.Sql.Builder
   
.Append("SELECT * FROM articles")
   
.Append("WHERE article_id=@0", id)
)

很管用吧,参数索引器来通过调用.Append是多么酷啊!【Big deal right? Well what's cool about this is that the parameter indicies are specific to each .Append call:】

var id=123;
var a=db.Query<article>(PetaPoco.Sql.Builder
   
.Append("SELECT * FROM articles")
   
.Append("WHERE article_id=@0", id)
   
.Append("AND date_created<@0",DateTime.UtcNow)
)

你也可以根据条件构建SQL:

var id=123;
var sql=PetaPoco.Sql.Builder
   
.Append("SELECT * FROM articles")
   
.Append("WHERE article_id=@0", id);

if(start_date.HasValue)
    sql
.Append("AND date_created>=@0", start_date.Value);

if(end_date.HasValue)
    sql
.Append("AND date_created<=@0", end_date.Value);

var a=db.Query<article>(sql)

注意到每个append调用都用到餐厨@0了吗?PetaPoco构建整个列表的参数,将这些参数索引更新到内部。

你也可以使用命名参数,然后他会在传递的参数中找到合适的属性名。

sql.Append("AND date_created>=@start AND date_created<=@end", 
               
new
               
{
                    start
=DateTime.UtcNow.AddDays(-2),
                    end
=DateTime.UtcNow
               
}
           
);

不管是数字的还是命名的参数,如果任何一个参数不能被推断出来,都会抛出一个异常。

这里还有几个创建SQL的公用方法:

var sql=PetaPoco.Sql.Builder()
           
.Select("*")
           
.From("articles")
           
.Where("date_created < @0",DateTime.UtcNow)
           
.OrderBy("date_created DESC");

跟踪Sql命令

有些时候能够看到执行的Sql语句会非常有用,PetaPoco为此提供了三个属性:

  • LastSQL - 非常明显,不解释
  • LastArgs - 传递的参数数组
  • LastCommand - SQL语句和参数字符串

在调试器中查看LastCommand属性能够简单的看到执行了那些操作!

OnException Handler Routine

PetaPoco所执行的Sql命令都封装在try/catch语句块中,所有的异常信息都会传递给OnException虚方法。通过记录这些异常(或在这个方法中设置断点),你可以轻松的跟踪那些地方出现了问题。

More

上面的内容展示了最基本的PetaPoco使用方法,想了解更多,请查看这些博客内容。

 

原文地址:http://www.toptensoftware.com/petapoco/

 

转载于:https://www.cnblogs.com/youring2/archive/2012/06/04/2532130.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494969.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

李飞飞公布谷歌云TPU、AutoML、行业方案等多项进展,AI云计算成谷歌全新增长点...

来源&#xff1a;全球人工智能摘要&#xff1a;7 月 24 日-26 日&#xff0c;Google Cloud NEXT 18 大会在美国旧金山举行。7 月 24 日-26 日&#xff0c;Google Cloud NEXT 18 大会在美国旧金山举行&#xff0c;Google Cloud作为谷歌人工智能未来业务发展的基础性平台&#xf…

new/delete和malloc/free的区别

malloc/free和new/delete的区别 共同点 都是从堆上申请空间&#xff0c;并且需要用户手动释放。 不同点 1、malloc/free是函数&#xff0c;new/delete是操作符。 2、malloc需要用户区手动计算空间的大小&#xff0c;new直接再后面跟上空间的类型就好。 3、malloc返回的是…

this的用法添加样式给tr或者div

onmouseover与onmouseout事件处理器&#xff0c;分别对应为鼠标移上去和鼠标移开时触发。οnmοuseοver"this.classNamemenu_title2;" 是鼠标移到该单元格上去时应用的css样式为“.menu_title2”的样式 οnmοuseοut"this.classNamemenu_title;"是鼠标离…

C语言中生成可执行程序的过程

预处理&#xff1a;展开头文件/进行宏替换/去掉注释/条件编译 编译&#xff1a;检查语法是否有错误&#xff0c;生成汇编代码 汇编&#xff1a;将汇编代码转换可供机器识别的机器码 链接&#xff1a;将多个文件链接到一起生成可执行程序

Gartner:2018年十大科技趋势与其对IT和执行的影响

来源&#xff1a;云技术实践摘要&#xff1a;Gartner每年发布的十大战略科技趋势一直备受关注&#xff0c;但企业往往会将50%以上的预算花在基础设施和执行上。因此&#xff0c;了解十大科技趋势与其对IT和执行的影响十分必要。在本周的Gartner CIO峰会期间&#xff0c;Gartner…

C++读取INI文件

Windows操作系统专门为此提供了6个API函数来对配置设置文件进行读、写&#xff1a;GetPrivateProfileInt() 从私有初始化文件获取整型数值GetPrivateProfileString() 从私有初始化文件获取字符串型值GetProfileInt 从win.ini 获取整数值GetProfileString 从win.ini 获取字符串值…

专栏 | 李航教授展望自然语言对话领域:现状与未来

来源&#xff1a;机器之心摘要&#xff1a;原华为诺亚方舟实验室主任、现已加入字节跳动 AI Lab的李航教授近日发表博客&#xff0c;对自然语言对话领域的现状和最新进展进行总结&#xff0c;并展望了未来的走向。1. 引言语音助手、智能客服、智能音箱、聊天机器人&#xff0c;…

浅析智能指针

为什么要有智能指针&#xff1f; 1.什么是智能指针&#xff1f; 智能指针是一个类&#xff0c;这个类的构造函数中传入一个普通指针&#xff0c;析构函数中释放传入的指针。智能指针的类都是栈上的对象&#xff0c;所以当函数&#xff08;或程序&#xff09;结束时会自动被释放…

论强化学习的根本缺陷

来源&#xff1a;AI 科技评论摘要&#xff1a;本文来自斯坦福大学博士生 Andrey Kurenkov 在 The Gradient 上发表的文章。在本文中&#xff0c;我们将讨论人工智能的一个核心领域——强化学习——的局限性。在这个过程中&#xff0c;起初我们将通过一个有趣的例子提出我们要讨…

c语言常用输出格式

在C语言中常用的是靠printf(" 输出的格式"&#xff0c;输出的内容); 来进行输出&#xff0c;所以要掌握一些关于输出的格式&#xff0c;下面将用代码的形式来简单说明&#xff1a; char c&#xff1b;char s[20]; int i1234;float f1.234567894567879; double d0.123…

辗转相除法--最大公约数/最大公倍数

什么是辗转相除法&#xff1f; 辗转相除法&#xff0c; 又名欧几里德算法&#xff08;Euclidean algorithm&#xff09;&#xff0c;是求最大公约数的一种方法。最早出现在公元前300年古希腊著名数学家欧几里得的《几何原本》》(第VII卷,命题i和ii)中。而在中国则可以追溯至东汉…

最后期限已至,高通收购恩智浦全剧终!中国一刀切断高通物联网全局梦!

来源&#xff1a;物联网智库摘要&#xff1a;没有一种商业模式可以永享特权。物联网时代&#xff0c;当专利和芯片两大支柱业务均受到剧烈冲击和威胁之下&#xff0c;如何创新以自救&#xff0c;正是考验高通全面战略能力的关键时刻&#xff0c;恩智浦是当前高通给出的最好答案…

DATEDIFF 函数使用

DATEDIFF 函数 [日期和时间] 返回两个日期之间的间隔 返回 Variant (Long) 的值&#xff0c;表示两个指定日期间的时间间隔数目。语法DateDiff(interval, date1, date2[, firstdayofweek[, firstweekofyear]])DateDiff 函数语法中有下列命名参数&#xff1a;部分 描述interval …

跳石板(通俗易懂的思路和方法)

所用到的知识 STL中的vector容器 动态规划思想 算法中的min 编程思想 将1 - M个看成一排&#xff0c;为其取个名字叫Slab&#xff08;数组&#xff09;&#xff0c;并在走之前将这一排石板都初始化为0&#xff0c;然后开始走&#xff0c;每到一块是班上就在这块是石板上写下…

使用sar进行性能分析

sar可用于监控Linux系统性能&#xff0c;帮助我们分析性能瓶颈。sar工具的使用方式为”sar [选项] intervar [count]”&#xff0c;其中interval为统计信息采样时间&#xff0c;count为采样次数。 下文将说明如何使用sar获取以下性能分析数据&#xff1a; 整体CPU使用统计各个C…

斯坦福证明神经网络能直接在光学芯片上训练

来源&#xff1a;全球人工智能摘要&#xff1a;据报道&#xff0c;美国斯坦福大学的研究人员已经证明&#xff0c;可以直接在光学芯片上训练人工神经网络。据报道&#xff0c;美国斯坦福大学的研究人员已经证明&#xff0c;可以直接在光学芯片上训练人工神经网络。这一重大突破…

蘑菇阵(动态规划)

题目&#xff1a; 现在有两个好友甲和B&#xff0c;住在一片长有蘑菇的由n * m个个方格组成的草地&#xff0c;A在&#xff08;1,1&#xff09;&#xff0c;B在&#xff08;N&#xff0c;M&#xff09;。现在甲想要拜访B&#xff0c;由于她只想去乙的家&#xff0c;所以每次她只…

用Keil-MDK开发TQ2440裸机程序入门教程——LED流水灯实现

觉得此编文章很详实&#xff0c;故转载之&#xff0c;来自http://www.amobbs.com/thread-5281512-1-1.html 开发板也差不多买了半年了, 以前照着教程用的是软件是ADS,在win7下老是崩溃, 后来才知道ADS早就不提供支持了, ADS的公司怎样怎样了...(此处省略300..) 然后我就捣鼓着怎…

关于量子计算,你应该知道的七个事实

来源&#xff1a;资本实验室摘要&#xff1a;在很多人眼中&#xff0c;量子计算机被认为能够完成经典计算机所不能完成的任务。聚焦前沿科技创新与传统产业升级在很多人眼中&#xff0c;量子计算机被认为能够完成经典计算机所不能完成的任务。事实上&#xff0c;如果量子计算机…

幸运袋子(详解)

题目分析 一个袋子里面有n个球&#xff0c;每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。 例如&#xff1a;如果袋子里面的球的号码是{1, 1, 2, 3}&#xff0c;这个袋子就是幸运的&#xff0c;因为…