Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案。Aoite.Data 适用于市面上大多数的数据库提供程序,通过统一封装,可以在日常开发中简单便捷的操作数据库。

【Aoite 系列 目录】

没有使用 Aoite 之前是这样的:

当你使用 Aoite 以后是这样的:

hah~~~你还不赶紧加入 Aoite GitHub 的大家庭吧!!

1. 快速入门

本小节将会使用 Microsoft SQL Server Compact 数据库作,一步一步的讲解针对数据库的增删改查。

1.1 首先,我们需要创建一个实体

class SimpleUser
{
[Column(true /* isPrimaryKey */)]
public string Username { get; set; }
public string Password { get; set; }
public string Memo { get; set; } public override string ToString()
{
return "Username:{0}\tPassword:{1}\tMemo:{2}".Fmt(this.Username, this.Password, this.Memo ?? "<NULL>");
}
}

实体的主键必须通过 Aoite.Data.ColumnAttribute 指定,若找不到此特性,框架还会尝试找到 Id 属性。若以上条件均不满足,操作过程中便可能直接抛出错误。

1.2 创建一个数据库引擎

var dbPath = GA.FullPath("Sample01.sdf");
if(File.Exists(dbPath)) File.Delete(dbPath); MsSqlCeEngine engine = new MsSqlCeEngine(dbPath, null /* password*/);
engine.CreateDatabase();

1.3 通过代码,创建一张表

engine.Execute(@"CREATE TABLE [SimpleUser]"
+ "([Username] nvarchar(50) NOT NULL PRIMARY KEY"
+ ", [Password] nvarchar(50) NOT NULL"
+ ", [Memo] nvarchar(500))")
.ToNonQuery() /* 执行查询命令,并返回受影响的行数结果。 */
.ThrowIfFailded(); /* 如果这个 SQL 语句出现异常,则直接抛出。 */

ToNonQuery:方法的内部原理是执行 DbCommand.ExecuteNonQuery,一般的新增、删除、修改等操作均可用此方法。

ThrowIfFailded:任何方法的调用都会有一个 Result(结果),而这个结果包含了 Value(值)、Status(状态码)和Message(消息)。ThrowIfFaildedUnsafeValue 的作用一致,在结果捕获到错误时,将会直接抛出异常。

通常定义 Result 的方法里,是不会直接抛出业务逻辑上的异常。方法的内部自然会包装好的这个异常,再返回给调用方。也就是说,返回的数据类型若是继承 System.Result,表示这个方法具有业务容错性

1.4 基本工作已完成。现在我们试着往数据库添加一条新纪录

engine.Add(new SimpleUser { Username = "admin", Password = "123456" })
.ThrowIfFailded(); Console.WriteLine("Add -> {0}", engine.FindOne<SimpleUser>("admin").UnsafeValue);

Add:这是一个扩展方法,通过高性能的反射,将对应的实体生成 INSERT 语句。

FindOne:这也是一个扩展方法,默认情况下是根据 Primary Key 去查找一条记录。

对于添加对象,还要介绍一种非常好用的方式,匿名方式:

engine.AddAnonymous<SimpleUser>(new { Username = "admin", Password = "123456" })
.ThrowIfFailded();

这样两种添加方式有什么区别吗?有!第一个生成的是完整的 INSERT 语句(包括 Simple.Memo),而 AddAnonymous 的 INSERT 语句不含 Simple.Memo

1.5 通过匿名方式,你还可以这样修改对象

engine.ModifyAnonymous<SimpleUser>(new { Username = "admin", Memo = "haha" })
.ThrowIfFailded();

匿名方式用于非常多的场景,最常见的比如:修改用户的密码,如果有 Modify,那么表里的这条记录所有数据都会被覆盖,而通过 ModifyAnonymous 方法,可以简单的 new { Id = id, Password = passowrd } 来生成更加简短的 UPDATE 语句。

同样,删除的时候,可以通过 RemoveAnonymous 删除指定主键的记录。

engine.RemoveAnonymous<SimpleUser>("admin")
.ThrowIfFailded();

你看,Aoite.Data 就是这么任性、好用、简单</span/>。

2. 上下文

显然,Aoite.Data 肯定不仅仅只有上个小节的那些内容。

上下文是 Aoite.Data 一个重要的概念。上个小节的所有执行的生命周期是这样的:

![简单连接的生命周期](http://images.cnblogs.com/cnblogs_com/sofire/656252/o_Sofire.Data simple execute.png)

倘若采用以下代码进行数据库操作,将会极大的浪费数据库资源:

var r1 = engine.Execute("sql1.....").ToNonQuery();
var r2 = engine.Execute("sql2.....").ToNonQuery();
var r3 = engine.Execute("sql3.....").ToNonQuery();
var r4 = engine.Execute("sql4.....").ToNonQuery();

显然,这种方式弱爆了。对于有严重开发洁癖的我们,怎能忍受这种代码呢?所以,上下文的目的是实现一次打开连接,多次执行,最后关闭连接,从而达到节省数据库连接池资源。可以通过以下方式:

using(var context = engine.Context)
{
//- context.Open(); 此句可以节省,在第一次执行命令时,如果连接还未打开,将会自动打开连接。
var r1 = context.Execute("sql1.....").ToNonQuery();
var r2 = context.Execute("sql2.....").ToNonQuery();
var r3 = context.Execute("sql3.....").ToNonQuery();
var r4 = context.Execute("sql4.....").ToNonQuery();
//- using 释放时,将会自动关闭,从而保证无论在哪一种情况(哪里系统崩溃)下都可以关闭连接。
}

开启事务有三种方式:

当然了,最重要的是,事务的结束之前,我们必须调用 context.Commit() 来提交事务,否则整个事务将会被丢弃。若希望手工回滚的话,可以调用 context.Rollback()

![上下文生命周期](http://images.cnblogs.com/cnblogs_com/sofire/656252/o_Sofire.Data context execute.png)

示例

我们紧接着前面的示例代码,采用上下文批量添加 10 条记录:

using(var context = engine.Context)
{
for(int i = 0; i < 10; i++)
{
context.Add(new SimpleUser { Username = "user" + i, Password = "123456" })
.ThrowIfFailded();
Console.WriteLine("数据库 RowCount -> {0}", engine.RowCount<SimpleUser>());
Console.WriteLine("上下文 RowCount -> {0}", context.RowCount<SimpleUser>());
}
}

上方代码输出如下所示:

数据库 RowCount -> 1
上下文 RowCount -> 1
数据库 RowCount -> 2
上下文 RowCount -> 2
数据库 RowCount -> ...
上下文 RowCount -> ...
数据库 RowCount -> 10
上下文 RowCount -> 10

我们来试着查询所有记录:

foreach(var item in engine.FindAllWhere<SimpleUser>().UnsafeValue)
{
Console.WriteLine(item);
}

FindAllWhere:根据指定筛选条件,查询指定泛型表的所有记录。

而采用事务的代码:

using(var context = engine.ContextTransaction)
{
for(int i = 10; i < 20; i++)
{
context.Add(new SimpleUser { Username = "user" + i, Password = "123456" })
.ThrowIfFailded();
Console.WriteLine("数据库 RowCOUNT -> {0}", engine.RowCount<SimpleUser>());
Console.WriteLine("上下文 RowCOUNT -> {0}", context.RowCount<SimpleUser>());
}
Console.WriteLine("事务提交前 数据库 RowCOUNT -> {0}", engine.RowCount<SimpleUser>());
context.Commit().ThrowIfFailded();
Console.WriteLine("事务提交后 数据库 RowCOUNT -> {0}", engine.RowCount<SimpleUser>());
}

以上代码的输出:

使用事务上下文...
数据库 RowCOUNT -> 10
上下文 RowCOUNT -> 11
数据库 RowCOUNT -> 10
上下文 RowCOUNT -> 12
数据库 RowCOUNT -> 10
上下文 RowCOUNT -> ...
数据库 RowCOUNT -> 10
上下文 RowCOUNT -> 20
事务提交前 数据库 RowCOUNT -> 10
事务提交后 数据库 RowCOUNT -> 20

3. 结束

关于 Aoite.Data 的简单介绍,就到此结束了,如果你喜欢这个框架,不妨点个推荐吧!如果你非常喜欢这个框架,那请顺便到Aoite GitHub Star 一下 :)

点此下载本文的所有示例代码。

问答:

  1. 是否开源:当然
  2. 单元测试:当然。覆盖率没达到 100%,但基本上 80% 的逻辑都有了单元测试。
  3. 有商用项目案例吗:!如:亚XXX得综合管理系统、亚XXX得门店系统、短信删除助手、XX通讯录(擦,这个名字我忘了)、店X宝虚拟充值平台、店X宝O2O商城、遛XXX电子商城……很多。
  4. 为什么现在不支持 ORACLE 或 Mysql 等数据库:支持。具体可参考 Aoite.Data 的前身 Sofire.Data。只不过现在为了将 Aoite.dll 瘦身,这些功能可以通过简单扩展可以快速的实现……

Aoite 系列(01) - 比 Dapper 更好用的 ORM的更多相关文章

  1. C# 数据操作系列 - 18 让Dapper更强的插件

    0. 前言 在前一篇中我们讲到了Dapper的应用,但是给我们的感觉Dapper不像个ORM更像一个IDbConnection的扩展.是的,没错.在实际开发中我们经常用Dapper作为对EF Core ...

  2. Aoite 系列 目录

    介绍 本项目从2009年孵化(V->Sofire->Aoite),至今已度过5个年头.一直在优化,一直在重构,一直在商用.有十分完整的单元测试用例.可以放心使用. Aoite on 博客园 ...

  3. Aoite 系列(02) - 超动感的 Ioc 容器

    Aoite 系列(02) - 超动感的 Ioc 容器 Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.Ioc 是一套解决依赖的最佳实践. 说 ...

  4. java io系列01之 "目录"

    java io 系列目录如下: 01. java io系列01之  "目录" 02. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括 ...

  5. Java 之 I/O 系列 01 ——基础

    Java 之 I/O 系列 目录 Java 之 I/O 系列 01 ——基础 Java 之 I/O 系列 02 ——序列化(一) Java 之 I/O 系列 02 ——序列化(二) 整理<疯狂j ...

  6. php从入门到放弃系列-01.php环境的搭建

    php从入门到放弃系列-01.php环境的搭建 一.为什么要学习php 1.php语言适用于中小型网站的快速开发: 2.并且有非常成熟的开源框架,例如yii,thinkphp等: 3.几乎全部的CMS ...

  7. Tkinter教程系列01——引言和安装Tk

    Tkinter教程系列01--引言和安装Tk 首发于我的个人博客 https://chens.life/tkinter-tutorial-chapter-01-introduction-and-ins ...

  8. Aoite 系列(04) - 强劲的 CommandModel 开发模式(上篇)

    Aoite 是一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案.Aoite.CommandModel 是一种开发模式,我把它成为"命令模型",这是一 ...

  9. SAP接口编程 之 JCo3.0系列(01):JCoDestination

    SAP接口编程 之 JCo3.0系列(01):JCoDestination 字数2101 阅读103 评论0 喜欢0 JCo3.0是Java语言与ABAP语言双向通讯的中间件.与之前1.0/2.0相比 ...

随机推荐

  1. Linux进程管理、任务管理

    查看进程 Linux中的进程可以使用ps.pstree命令查看. 一般使用 ps aux (注意,没有短划线-:虽然加上不影响执行,只是会提示),还可以使用 ps -le,都是查看所有进程,区别在于显 ...

  2. win10 EFI装ubuntu14.04双系统 及初始配置

    这次第二次装ubuntu系统了,第一次是在win7下安装的,到了win10,由于用了efi,跟win7的安装方法不太相同,相同点有: 1.仍然可以用u盘启动,我用的是UltroISO这个软件. 2.装 ...

  3. heap c++ 操作 大顶堆、小顶堆

    在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.c ...

  4. github基本操作

    http://www.cnblogs.com/SeeYouBug/p/6193527.html#3583637

  5. 去重 ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字段) RN

    关键字  ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字段) RN 按照分组字段进行排序并标编号 ROW_NUMBER() OVER(PARTITIO ...

  6. java的三元运算符

    1.三元运算符语法:判断表达式?表达式1:表达式2: (1)三元运算符适合于判断2个值到底使用哪一个! public static void mian(String[] args){ int sex= ...

  7. css两列自适应布局的多种实现方式及原理。

    两列布局是非常常见的需求在实际项目中,实现的方式也有很多.究其原理也都不算复杂.这里主要提出几种实现方式和原理. html页面基本布局如下代码所示: 1 <div class="mai ...

  8. jfinal框架页面找不到相关css,js文件404

    在JFinalConfig中添加配置: @Override public void configHandler(Handlers handlers) { handlers.add(new Contex ...

  9. Android系统启动顺序

    Android是一个基于Linux的开源操作系统.x86(x86是一系列的基于intel 8086 CPU的计算机微处理器指令集架构)是linux内核部署最常见的系统.然而,所有的Android设备都 ...

  10. 转载扩展Windows Mobile模拟器存储空间的方法

    扩展Windows Mobile模拟器存储空间的方法 在Windows Mobile应用程序开发的初期,可以使用SDK自带的模拟器来进行调试,这给我们开发人员提供了一种方便的途径.一般的应用程序,占用 ...