我的ORM之一 -- 查询
概述
http://code.taobao.org/svn/MyOql/
这是我自己写的开源ORM教程,我想先从场景示例中切入介绍,先有一个感性的认识,以小见大,触类旁通,有了这个认识,就能自行扩展出更多的用法。
数据常用操作 CURD,ORM也一样。
ORM生成的实体应该有一个根,我们叫它: dbr ( db root )
假设有一些表:如 Menu表 , User 表 等。
生成的两类表对象:
- 一个对象是元数据,表示数据库的结构,如有哪些列,哪些是主键,哪些是自增键,以及列的类型。生成 MenuRule
- 另一个对象用来存放真实的数据。生成 MenuRule+Entity
在Rule类中生成实体类。如:
public class MenuRule : RuleBase
{ public class Entity
{ public string Name; } public ColumnDefine Name;
}
一个系统,可以按模块分解;一个大系统可以分解为多个小的系统。Mvc可以按模块分成多个Area,数据库表也应该符合这个规则。
对数据库表进行分组,如:平台组,Erp组,Hr组,财务组。在引用的时候,按组进行引用,如: dbr.PlateForm.User , dbr.Erp.Income , dbr.Hr.UserJob , dbr.Money.Banlance ...
查询写法:
1. 普通查询:
dbr.表
.Select(列)
.Join(它表,On关系,它表的列)
.Where(条件)
.Skip(分页跳过条数)
.Take(分页条数)
.GroupBy(分组)
.Having(分组过滤)
.OrderBy(排序)
.ToEntityList(默认实体对象);
例子:
C#:
List<MenuRule.Entity> results = dbr.Menu .Select(o=>new Columns(){ o.Id,o.Name }) .Where(o=> o.Id> ) .Skip() .Take() .ToEntityList(o=>o._) ;
生成SQL:
Select * From
( Select Row_Number() Over (Order by [ID] asc) As [#__IgNoRe__AutoId], * From
(
select
[Menu].[ID] As [Id],
[Menu].[Name] As [Name]
From [S_Menu] As [Menu]
where [Menu].[ID] > 0
) As [__SubQuery__] ) As [___SubQuery___]
where [#__IgNoRe__AutoId] between 11 and 20
2. From子查询
要生成的SQL:
select
[a].[m] As [m],
[a].[ShortName] As [ShortName]
From (
select
min([City].[ID]) As [m],
[City].[ShortName] As [ShortName]
From [S_City] As [City]
group by [City].[ShortName]
) As [a]
where [a].[ShortName] Like '%河%' And [a].[m] = 1
Order by [#__IgNoRe__1] asc
C#写法:
dbr.City.Select(o => new Columns() { o.Id.Min().As("m") , o.ShortName })
.AutoGroup()
.SelectWrap("a")
.Where(o => o.ShortName.Contains("河") & new RawColumn(System.Data.DbType.Int32 , "a","m") == )
.OrderBy(o=>o.ShortName.Asc)
.ToMyOqlSet() ;
3.Join子查询
select
[ProductInfo].[ID] As [Id],
[ProductInfo].[ProductTypeID] As [ProductTypeID],
[ProductInfo].[CarInfoID] As [CarInfoID],
[ProductInfo].[Name] As [Name],
[ProductInfo].[Logo] As [Logo],
[ProductInfo].[Remark] As [Remark],
[ProductInfo].[Price] As [Price],
[ProductInfo].[SortID] As [SortID],
[ProductInfo].[PlatCost] As [PlatCost],
[ProductInfo].[Color] As [Color],
[ProductInfo].[Unit] As [Unit],
[ProductInfo].[CorpID] As [CorpID],
[ProductInfo].[Status] As [Status],
[ProductInfo].[Group] As [Group],
[ProductInfo].[CreateAt] As [CreateAt],
[ProductInfo].[UpdateAt] As [UpdateAt],
[ProductInfo].[CreateBy] As [CreateBy],
[ProductInfo].[StandardPrice] As [StandardPrice],
[ProductInfo].[IsSuitCar] As [IsSuitCar],
[ProductInfo].[ParentProductID] As [ParentProductID]
From [P_ProductInfo] As [ProductInfo] left join(select
[PUser].[ID] As [Id],
[PUser].[Name] As [Name]
From [P_User] As [PUser]
where [PUser].[ID] > 100) As b on ([ProductInfo].[CreateBy] = [b].[Id])
Order by [ProductInfo].[ID] asc
C#:
dbr.PlatForm.ProductInfo.Select()
.Join(SqlKeyword.LeftJoin, dbr.PUser.Select(o => new Columns(o.Id, o.Name)).Where(o => o.Id > ).As("b") , (a, b) => a.CreateBy == new RawColumn(System.Data.DbType.Int32,"b","Id") )
.ToMyOqlSet();
4. 树查询:
使用SQL的 With ... As 做一个树查询,在此结果上,再做查询。SQL写法:
with [ProductType] as (
select * from [P_ProductType] where [CorpID] = 1 And [PID] = 0
union all
select t.* from [ProductType] as p join [P_ProductType] as t on ( p.[ID] = t.[PID])
)select
[ProductType].[ID] As [Id],
[ProductType].[Name] As [Name],
[ProductType].[CarInfoID] As [CarInfoID],
[ProductType].[PID] As [Pid],
[ProductType].[Wbs] As [Wbs],
[ProductType].[CarGroup] As [CarGroup],
[ProductType].[Remark] As [Remark],
[ProductType].[SortID] As [SortID],
[ProductType].[CorpID] As [CorpID],
[ProductType].[CreateAt] As [CreateAt],
[ProductType].[CreateBy] As [CreateBy],
[ProductType].[Status] As [Status],
[ProductType].[Logo] As [Logo],
[ProductType].[IsLeaf] As [IsLeaf],
[PUser].[Name] As [CreateByName]
From [ProductType]
inner join [P_User] As [PUser] on ([ProductType].[CreateBy] = [PUser].[ID])
where [ProductType].[CorpID] = 1
Order by [ProductType].[ID] asc
C#:
dbr.PlatForm.ProductType
.SelectTree(null, o => o.CorpID == & o.Pid == , o => o.Pid, o => o.Id)
.Join(dbr.PUser, (a, b) => a.CreateBy == b.Id, b => b.Name.As("CreateByName"))
.Where(o => o.CorpID == )
.ToMyOqlSet();
连接列
选择一个符号,将多个列连接起来,组合为一个列集合。可重载的运算符:https://msdn.microsoft.com/zh-cn/library/8edha89s(v=vs.80).aspx
由于大部分运算符被SQL运算符优先使用,所以只能选持一个生僻的运算符。仅剩余 ^ 可使用。
使用 ^ 可以连接多个列,这是最简单的方法:
dbr.Menu.Select(o=>o.Id ^ o.Name)
普通方式:
dbr.Menu.Select(o=>new Columns(o.Id,o.Name))
使用SQL自定义函数
数据库函数分为:表值,标量,聚合,系统四大类。
表值函数:
表值函数的特点和表差不多,可以理解为带参数的表。它可以像表一样,利用实体生成器生成结构。
如Split 函数,输入字符串,返回按","分隔的表。
SQL:
select
[Split].[Value] As [Value]
From [Split]('abc,def') As [Split]
where [Split].[Value] Like '%b%'
C#:
dbr.Split("abc,def")
.Select()
.Where(o => o.Value.Contains("b"))
.ToMyOqlSet() ;
标量函数:
标量函数需要利用 C#扩展方法,对列进行扩展,如:
public static WhereClip IsSameDay(this ColumnClip column, DateTime Dt)
{
var retVal = new RawColumn(DbType.Boolean);
retVal.Expression = "dbo.F_IsSameDay({0},{1})";
retVal.Parameter = new Columns() { column.Clone() as ColumnClip, new ConstColumn(Dt) }.Embattle();
return retVal == ;
}
判断两个值是否是同一天:输入两个时间值,返回bit。
SQL:
select
[PUser].[ID] As [Id],
[PUser].[LoginName] As [LoginName],
[PUser].[Name] As [Name],
[PUser].[QQOpenID] As [QQOpenID],
[PUser].[Logo] As [Logo],
[PUser].[Score] As [Score],
[PUser].[Type] As [Type],
[PUser].[BirthDay] As [BirthDay],
[PUser].[IDCard] As [IDCard],
[PUser].[IDCardPhoto] As [IDCardPhoto],
[PUser].[Email] As [Email],
[PUser].[Sex] As [Sex],
[PUser].[Mobile] As [Mobile],
[PUser].[ImName] As [ImName],
[PUser].[ImNum] As [ImNum],
[PUser].[ValidateStatus] As [ValidateStatus],
[PUser].[CreateAt] As [CreateAt],
[PUser].[WorkType] As [WorkType],
[PUser].[CityID] As [CityID],
[PUser].[MaritalStatus] As [MaritalStatus],
[PUser].[NPCityID] As [NPCityID],
[PUser].[CorpID] As [CorpID],
[PUser].[IsCorpAdmin] As [IsCorpAdmin],
[PUser].[BankID] As [BankID],
[PUser].[BankNo] As [BankNo],
[PUser].[BankDetailName] As [BankDetailName]
From [P_User] As [PUser]
where dbo.F_IsSameDay([PUser].[CreateAt],'2015-05-26 00:00:00') = 1
C#:
dbr.PUser
.Select()
.Where(o => o.CreateAt.IsSameDay("2015-05-26".AsDateTime()))
.ToMyOqlSet();
聚合函数:
聚合函数,要带有GroupBy,分组进行计算。聚合函数也需要自行扩展,如JoinStr 函数:
public static ColumnClip JoinStr(this ColumnClip column)
{
var retVal = new RawColumn(DbType.String);
retVal.Expression = "dbo.JoinStr({0})";
retVal.IsPolymer = true;
retVal.Parameter = column.Clone() as ColumnClip;
return retVal;
}
SQL:
select
dbo.JoinStr([PUser].[Name])
From [P_User] As [PUser]
where dbo.F_IsSameDay([PUser].[CreateAt],'2015-05-26 00:00:00') = 1
C#:
dbr.PUser
.Select(o=>o.Name.JoinStr())
.Where(o => o.CreateAt.IsSameDay("2015-05-26".AsDateTime()))
.ToMyOqlSet();
如果扩展系统函数,可以按上述方式进行。看系统函数是哪一类。
使用存储过程:
存储过程,在形式上就像一个函数,有输入参数,有返回值。可以使用代码生成器搞定。
调用:
PUserRule.Entity user = dbr.P_Login("admin","") ;
支持的关键字:
Case When关键字:
C#:
dbr.PUser
.Select(o =>new Columns( o.Id, o.Name.JoinStr() ) )
.Where(o => o.CreateAt.IsSameDay("2015-05-26".AsDateTime()))
.OrderBy(o =>
dbo.CaseWhen(dbr.PUser.Id < , new ConstColumn())
.WhenThen(dbr.PUser.Id.Between(, ), new ConstColumn())
.ElseEnd(new ConstColumn())
.Asc)
.AutoGroup()
.ToMyOqlSet();
Sql:
select
[PUser].[ID] As [Id],
dbo.JoinStr([PUser].[Name])
From [P_User] As [PUser]
where dbo.F_IsSameDay([PUser].[CreateAt],'2015-05-26 00:00:00') = 1
group by [PUser].[ID]
Order by Case When [PUser].[ID] < 100 Then 1 When ([PUser].[ID] Between 100 And 200) Then 2 Else 3 End asc
其它关键字很简单,就不示例了:
运算符:
加(+) ,减(-) ,乘(×),除(÷) ,等于(=),不等于(!=),大于(>),小于(<),大于等于(≥),小于等于(≤),And (&),Or(|),求模(%)
关键字:
As,BitAnd,BitOr,In,NotIn,Like,Exists,NotExists,Escape, Between,NotBetween,Cast,IsNull,Union,UnionAll,Now
字符串函数:
Len,SizeOf(DataLength),Left,Right,Reverse,AscII,Unicode,Char,NChar,StringIndex,SubString,Stuff,PatIndex,Replace,IsNumeric,LTrim,RTrim,Trim
聚合函数:
Count,CountDistict,Sum,Max,Min,Avg
时间函数:
IsDate,Year,Month,Day,DateDiff,DateAdd
数字函数:
Abs,Sign,Floor,Ceiling,Power,Square,Sqrt,Random。
我的ORM之一 -- 查询的更多相关文章
- Django的ORM常用查询操作总结(Django编程-3)
Django的ORM常用查询操作总结(Django编程-3) 示例:一个Student model: class Student(models.Model): name=models.CharFiel ...
- tornado 07 数据库—ORM—SQLAlchemy—查询
tornado 07 数据库—ORM—SQLAlchemy—查询 引言 #上节课使用query从数据库查询到了结果,但是query返回的对象是直接可用的吗 #在query.py内输入一下内容 from ...
- Django之ORM优化查询的方式
ORM优化查询的方式 一.假设有三张表 Room id 1 2 .. 1000 User: id 1 .. 10000 Booking: user_id room_id time_id date 1 ...
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- Net/NetCore/.NET5 ORM 六大查询体系 - SqlSugar 高级篇
框架介绍 SqlSugar ORM是一款老牌国产ORM框架,生命力也比较顽强,从早期ORM不成熟阶段,一直存活到现在,我为什么要一直坚持,那是因为还有很多用户在使用,本来我能够较早推出新开源框架 ,可 ...
- Moon.Orm 常见查询实例
一.Moon.Orm框架总述 (您还用hibernate?实体框架?) 1.框架名:Moon 意思是月亮,而非Mono.因为很喜欢明月,所以以此为名.它是一个.NET下的Orm框架. 2.发展历史:历 ...
- beego中orm关联查询使用解析
这两天在学习beego框架,之前学习的时候遗漏了很多东西,比如orm.缓存.应用监控.模板处理等,这里将通过实例记录下如何使用beego自带的orm进行关联查询操作. 首先说明下,beego的orm有 ...
- Dos.ORM Select查询 自定义列
自定义列 .Select( p = >new{ test = p.id}) // 同sql 列名 as 新列名 如下是 自己在写代码的例子,查询,分页,where条件,排序 var where ...
- laravel Eloquent ORM联合查询出现Class not found,就算在Moel中存在这个类
今天发现一个坑,在处理Eloquent ORM的联合查询时,一直报错Class 'AdminGroup' not found ,可是我的项目中明明存在这个类,如下 这是我的模型类: 它们的控制器方法: ...
随机推荐
- <停车卫> 产品需求说明书 version 2.0
<停车卫> 产品需求说明书 文档版本号: Version 2.0 文档编号: xxxx 文档密级: 归属部门/项目: 产品名: 停车卫 子系统名: 编写人: kina 编写日期: 2015 ...
- eyegaze
1. eye_gaze https://github.com/iitmcvg/eye-gaze 2.deepgaze https://github.com/mpatacchiola/deepgaze ...
- RTMP协议中文翻译(首发)(转)
Adobe公司的实时消息传输协议 摘要 此备忘录描述了 Adobe公司的实时消息传输协议(RTMP),此协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和 ...
- eclipse在光标停留在同一对象的背景色提示,开启与关闭
eclipse在光标停留在变量上的时候,同一变量能够提示相同的背景色.这个功能感觉不起眼,但是实在是很好用啊.如果不小心点消失了会很麻烦. 这里留个记录,如果关闭了记得开启: 开启关闭的位置在工具栏上 ...
- java中用spring实现数组类型输出
java 中的几个数组类型 1.Department类 package com.yy.collection; import java.util.List; import java.util.Map; ...
- 运费模版源码(.net)
之前写了一篇关于nop商城系统中运费模版模块相关的随笔,说要把源码贴出来,一直没有贴,现在我把源码贴出来,有任何问题欢迎留言讨论. 源码是在nop上写的,所以文件夹结构和nop的文件夹对应,源码包含的 ...
- Rancher 快速上手指南操作(1)
Rancher 快速上手指南操作(1)该指南知道用户如何快速的部署Rancher Server 管理容器.前提是假设你的机器已经安装好docker了.1 确认 docker 的版本,下面是 ubunt ...
- js动态时间
一.在<head></head> 之间写入下面js代码 <script type="text/javascript" language="J ...
- Selenium2+python 常用函数汇总
1. driver = webdriver.Chrome() --新建实例 2.driver.find_element_by_id("username") ---通过标签属性id ...
- linux下svn常用命令
(如果是第一次提交文件,很可能会出现“svn:'.'不是工作副本”,即当前目录不是工作副本,这个时候需要用到import: eg:svn import . url) 1.将文件checkout到本地目 ...