扯淡

这是一款轻量、高效的.NET C#数据库访问框架(ORM)。查询接口借鉴 Linq(但不支持 Linq)。借助 lambda 表达式,可以完全用面向对象的方式就能轻松执行多表连接查询、分组查询、聚合函数查询、插入数据、删除和更新满足条件的数据等操作。

上篇文章中, Chloe.ORM 初次对外抛头露面,虽然是在重复造轮子,但还是得到部分园友的支持与认可,LZ非常感谢!上文主要展示 Chloe 的查询方式以及支持的 lambda 写法,本文主题是多表连接查询、插入数据、更新数据、删除数据以及事务支持。

导航

Chloe.ORM

事前准备

实体:

public enum Gender
{
Man = 1,
Woman
} [Table("Users")]
public class User
{
[Column(IsPrimaryKey = true)]
[AutoIncrement]
public int Id { get; set; }
public string Name { get; set; }
public Gender? Gender { get; set; }
public int? Age { get; set; }
public int? CityId { get; set; }
public DateTime? OpTime { get; set; }
}

首先,创建一个 DbContext:

IDbContext context = new MsSqlContext(DbHelper.ConnectionString);

再创建一个 IQuery<T>:

IQuery<User> q = context.Query<User>();

多表连接查询

在上篇文章中,介绍了 Chloe 的查询功能。Chloe 执行连接查询时,建立连接(IQuery<T>接口调用 InnerJoin、LeftJoin、RightJoin 和 FullJoin)返回的是 IJoiningQuery 的泛型对象,如果看过框架源码的同学可能会知道,IJoiningQuery 的泛型参数最多有5个,而且有5个泛型参数的那个类(IJoiningQuery<T1,T2,T3,T4,T5>)就只有一个 Select 方法,也就是说不能继续连接其它表,最多有5个表建立连接,真的是这样吗?如果你这样认为你就错了!我们来看看怎么建立超过5个表的连接。

伪代码:

//假设已经有5个表建立了连接的对象为 jq_q1_q5
IJoiningQuery<T1, T2, T3, T4, T5> jq_q1_q5 = null; //jq_q1_q5 调用 Select 方法,返回一个包含 T1-T5 的 IQuery<T> 对象 view_q1_q5
var view_q1_q5 = jq_q1_q5.Select((t1, t2, t3, t4, t5) => new { T1 = t1, T2 = t2, T3 = t3, T4 = t4, T5 = t5 }); //假设第6个表的 IQuery<T6> 对象为 q6
IQuery<T6> q6 = null; //这时,view_q1_q5 与 q6 建立连接,返回 IJoiningQuery 对象 jq
var jq = view_q1_q5.InnerJoin(q6, (t1_t5, t6) => t1_t5.T5.XX == t6.XXX); //然后我们调用 jq 的 Select 方法,返回一个包含 T1-T6 的 IQuery<T> 对象 view。
//view 又是一个 IQuery<T> 对象,泛型参数为包含 T1-T6 所有信息的匿名对象(这时候还没有发起 sql 查询哦),拿到它,我们就可以为所欲为了。
var view = jq.Select((t1_t5, t6) => new { T1 = t1_t5.T1, T2 = t1_t5.T2, T3 = t1_t5.T3, T4 = t1_t5.T4, T5 = t1_t5.T5, T6 = t6 }); //可以直接查出数据库中 T1-T6 的所有信息
view.ToList(); //也可以选取 T1-T6 中我们想要的字段
view.Select(a => new { a.T1.xx, a.T2.xx, a.T3.xx /*...*/}).ToList();

这样,周而复始,就可以实现无限表连接了,相对没有 Linq 那么直观,但这是我能想到最好的方式了。如果哪位同学有更好的设计,望分享,不胜感激!

Chloe 的另外亮点是聚合函数查询和分组查询,这两个查询有别于 Linq,更趋于标准 sql 思想,配合连接查询使用,可以应对一些稍微复杂的查询,可以翻看上篇文章使用进阶部分,有简单介绍,连接地址:http://www.cnblogs.com/so9527/p/5636216.html#more_usage

目前市面上很多 ORM 都只是支持单表查询,能灵活操作连接查询和聚合函数查询的,除 EF 和 linq to sql 外,为数不多,这也是我造轮子的原因之一。

插入数据

方式1

以 lambda 的形式插入:

IDbContext context = new MsSqlContext(DbHelper.ConnectionString);

//返回主键 Id
int id = (int)context.Insert<User>(() => new User() { Name = "lu", Age = 18, Gender = Gender.Man, CityId = 1, OpTime = DateTime.Now });
/*
* INSERT INTO [Users]([Name],[Age],[Gender],[CityId],[OpTime]) VALUES(N'lu',18,1,1,GETDATE());SELECT @@IDENTITY
*/

方式2

IDbContext context = new MsSqlContext(DbHelper.ConnectionString);

User user = new User();
user.Name = "lu";
user.Age = 18;
user.Gender = Gender.Man;
user.CityId = 1;
user.OpTime = new DateTime(1992, 1, 16); //会自动将自增 Id 设置到 user 的 Id 属性上
user = context.Insert(user);
/*
* String @P_0 = "lu";
Gender @P_1 = Man;
Int32 @P_2 = 18;
Int32 @P_3 = 1;
DateTime @P_4 = "1992/1/16 0:00:00";
INSERT INTO [Users]([Name],[Gender],[Age],[CityId],[OpTime]) VALUES(@P_0,@P_1,@P_2,@P_3,@P_4);SELECT @@IDENTITY
*/

第一种方式比较接近 sql 的写法,可以有选择的插入。第二种方式则会将所有映射的字段都插入。对于插入数据需求,这两种方式我想应该可以满足了。

更新数据

方式1

以 lambda 的形式更新:

MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString);

context.Update<User>(a => new User() { Name = a.Name, Age = a.Age + 100, Gender = Gender.Man, OpTime = DateTime.Now }, a => a.Id == 1);
/*
* UPDATE [Users] SET [Name]=[Users].[Name],[Age]=([Users].[Age] + 100),[Gender]=1,[OpTime]=GETDATE() WHERE [Users].[Id] = 1
*/ //批量更新
//给所有女性朋友年轻 10 岁
context.Update<User>(a => new User() { Age = a.Age - 10, OpTime = DateTime.Now }, a => a.Gender == Gender.Woman);
/*
* UPDATE [Users] SET [Age]=([Users].[Age] - 10),[OpTime]=GETDATE() WHERE [Users].[Gender] = 2
*/

方式2

MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString);

User user = new User();
user.Id = 1;
user.Name = "lu";
user.Age = 28;
user.Gender = Gender.Man;
user.OpTime = DateTime.Now; context.Update(user); //会更新所有映射的字段
/*
* String @P_0 = "lu";
Gender @P_1 = Man;
Int32 @P_2 = 28;
Nullable<Int32> @P_3 = NULL;
DateTime @P_4 = "2016/7/8 11:28:27";
Int32 @P_5 = 1;
UPDATE [Users] SET [Name]=@P_0,[Gender]=@P_1,[Age]=@P_2,[CityId]=@P_3,[OpTime]=@P_4 WHERE [Users].[Id] = @P_5
*/ /*
* 支持只更新属性值已变的属性
*/ context.TrackEntity(user);//在上下文中跟踪实体
user.Name = user.Name + "";
context.Update(user);//这时只会更新被修改的字段
/*
* String @P_0 = "lu1";
Int32 @P_1 = 1;
UPDATE [Users] SET [Name]=@P_0 WHERE [Users].[Id] = @P_1
*/

像第一种方式可以批量更新数据方法,我觉得在实际开发中很有必要,且不可或缺。

之前,同事用 EF 开发一个功能,需要批量更新,他的做法是将所有满足条件的数据给查出来,然后挨个赋值,最后统一 SaveChanges(),开发时由于数据量少,没发现问题。部署上线了以后,用户随便点击一下保存,这个方法执行都要好久,瞬间懵了,不多说为什么,你懂的!虽然有人基于 EF 做了一个支持批量更新的 EF 扩展类库,经过各方面考虑,最终不敢轻易冒风险引入项目中。那就拼接一句批量 Update 的sql呗,原生态执行。Oh!想到拼 sql,心中一万个草泥马路过!!!都 .net4.5+ 时代,.net Core 都出了,还执着手写sql?这费时费力的活咱90后程序员可不干!虽然我 sql 写得很溜,但不到没辙的时候我是不会去拼 sql。项目开发阶段,我是秉着怎么快怎么做原则,有能10分钟解决问题的方式,我是不会选择10分钟+1秒的其他方法!多一秒也不行!至于优化,那是后事。
自己动手,能根据需求定制理想的功能,这也是我造轮子的原因之一。

删除数据

方式1

以 lambda 的形式删除:

MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString);

context.Delete<User>(a => a.Id == 1);
/*
* DELETE [Users] WHERE [Users].[Id] = 1
*/ //批量删除
//删除所有不男不女的用户
context.Delete<User>(a => a.Gender == null);
/*
* DELETE [Users] WHERE [Users].[Gender] IS NULL
*/

方式2

MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString);

User user = new User();
user.Id = 1;
context.Delete(user);
/*
* Int32 @P_0 = 1;
DELETE [Users] WHERE [Users].[Id] = @P_0
*/

删除数据就这么简单。

事务支持

Chloe 的事务操作方法在 DbContext.CurrentSession 属性里:

MsSqlContext context = new MsSqlContext(DbHelper.ConnectionString);

IDbSession dbSession = context.CurrentSession;
try
{
dbSession.BeginTransaction(); //to do somethings here... dbSession.CommitTransaction();
}
catch
{
dbSession.RollbackTransaction();
}

事务是每个 ORM 必备的功能。太简单,本来不想写进来的,想想,写吧,凑个字数也好。

结语

Chloe.ORM 主打便捷、高效,无论是 IDbContext 还是 IQuery<T> 接口,设计极其简单,基本一看就懂,一用就会。并且不依赖任何配置,上手简单,传个数据库连接字符串就能跑,我就喜欢这样傻瓜式开发。话说有一点我很纳闷,C# 是一门高度简化的语言,很多人说微软把程序员培养得越来越傻,试问,傻瓜式开发不好吗?这是开发语言的进步啊,我们为什么要拒绝!那些人是不是都喜欢折腾?说句不好听的,如果一门语言真把一个程序员变“傻”,我想,那位程序员肯定不是好程序员!扯远了,嘿嘿。

秉着开源共享精神,促进国内开源事业发展,Chloe.ORM 完全开源,遵循 Apache2.0 协议。

GitHub:https://github.com/shuxinqin/Chloe

开源中国:http://www.oschina.net/p/chloe-orm

ps:小弟不才,文化、技术功底有限,必有不足之处,望各路大神多多指点,非常感谢。也请有异议的同学,点反对的同时,麻烦也留个建议再离开,行吗?谢谢。

[开源]无sql之旅-Chloe.ORM之增删查改的更多相关文章

  1. SQL Server 中BIT类型字段增删查改那点事

    话说BIT类型字段之前,先看“诡异”的一幕,执行Update成功,但是查询出来的结果依然是1,而不是Update的2 当别人问起我来的时候,本人当时也是处于懵逼状态的,后面联想具体的业务突然想起来这个 ...

  2. [开源].NET数据库访问框架Chloe.ORM

    扯淡 13年毕业之际,进入第一家公司实习,接触了 EntityFramework,当时就觉得这东西太牛了,访问数据库都可以做得这么轻松.优雅!毕竟那时还年轻,没见过世面.工作之前为了拿个实习机会混个工 ...

  3. 常用SQL语句(增删查改、合并统计、模糊搜索)

    转自:http://www.cnblogs.com/ljianhui/archive/2012/08/13/2695906.html 常用SQL语句 首行当然是最基本的增删查改啦,其中最重要的是查. ...

  4. Sql Server的艺术(一) 视图的增删查改

    视图是从一个或者多个表中查询数据的另一种方式.利用视图可以集中.简化定制数据库,同时还能保障安全. 视图其结构和数据是建立在对应的查询基础上的.和表一样,视图也是包括几个被定义的数据列和多个数据行,但 ...

  5. SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...

  6. SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码) 概述: 表由行和列组成,每个表都必须有个表名. SQL CREATE TABLE 语法 CREATE TABLE tabl ...

  7. EF各版本增删查改及执行Sql语句

    自从我开始使用Visual Studio 也已经经历了好几个版本了,而且这中间EF等框架的改变也算是比较多的.本篇文章记录下各个版本EF执行Sql语句和直接进行增删查改操作的区别,方便自己随时切换版本 ...

  8. EF增删查改加执行存储过程和sql语句,多种方法汇总

    ActionUrl c = new ActionUrl() { ActionName="test", RequestUrl="/123/123", SubTim ...

  9. JDBC终章- 使用 DBUtils实现增删查改- C3P0Utils数据源/QueryRunner runner连接数据源并执行sql

    JDBC终章- 使用 DBUtils实现增删查改 1.数据库结构 Create Table CREATE TABLE `user` ( `id` ) NOT NULL AUTO_INCREMENT, ...

随机推荐

  1. ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态

    原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...

  2. c#面向对象基础技能——学习笔记(三)基于OOP思想研究对象的【方法】

    实例方法:(解决问题的步骤)完成某功能的各种语句的组合 编写方法要考虑的内容: 1.通过项目需求,确定各方法的任务.功能: 2.方法的可访问性(默认是private):(字段private 属性int ...

  3. 决策树ID3算法的java实现(基本试用所有的ID3)

    已知:流感训练数据集,预定义两个类别: 求:用ID3算法建立流感的属性描述决策树 流感训练数据集 No. 头痛 肌肉痛 体温 患流感 1 是(1) 是(1) 正常(0) 否(0) 2 是(1) 是(1 ...

  4. 三大框架之hibernate入门

    hibernate入门   1.orm      hibernate是一个经典的开源的orm[数据访问中间件]框架           ORM( Object Relation Mapping)对象关 ...

  5. R语言:常用统计检验

    统计检验是将抽样结果和抽样分布相对照而作出判断的工作.主要分5个步骤: 建立假设 求抽样分布 选择显著性水平和否定域 计算检验统计量 判定 -- 百度百科 假设检验(hypothesis test)亦 ...

  6. node-sass报错解决方法

    在Vue.js中,每一个vue文件都是一个组件,在.vue文件中可以将模板,脚本,样式写在一起,便于组织整个组件.在使用template,script时,编写css样式时,都进行的特别顺利,唯独当我想 ...

  7. maven 打包含有第三方依赖的 jar 包

    maven 打包含有第三方依赖的 jar 包:mvn assembly:assembly

  8. Mac 开发者常用的工具

    转载:http://www.oschina.net/news/53946/mac-dev-tools 在写 Mac 程序员的十个武器之前,我决定先讲一个故事,关于 Mac 和爱情的.(你们不是问 Ma ...

  9. MVC 后台管理框架 FineUIMvc 在线示例

     FineUIMvc 在线示例 基础版下载

  10. 12、产品经理要阅读的书籍 - IT软件人员书籍系列文章

    产品经理是软件产品的主要领导者.不同于项目经理,产品经理是对产品负责,更多的是负责产品的设计定型:而项目经理则对项目负责,更多的是负责项目软件的实现.产品经理的一些工作,和项目经理是一致的,比如需求分 ...