比LINQ简单:PDF.NET框架之OQL语言!

bluedoctor 2010-03-28 06:17:32
LINQ很强大,但它要.NET3.0以上才支持,如果还在用VS2005的朋友就有点感叹了,为啥面向对象的方式写SQL的LINQ不能用?
如果你想了解LINQ的实现原理,不想自己实现一个LINQ试试看?
另外,如果你的客户之装了.NET2.0框架,不想装.NET3.5怎么办?

----------------------
基于这些问题,你有兴趣的可以看看 PDF.NET框架之OQL语言!

OQL:Object Query Language
[实体]对象查询语言


OQL作为PDF.NET框架的一部分,为整个框架基于实体的查询提供了强大的“查询语言表达式”!

下面举例介绍OQL的使用:
--------------------------
PDF.NET之实体查询


1.1.1.1 实体类
实体类都是继承自PDF.NET的Entity基类的类。
例如我们假设数据库中存在一个通过如下建表语句创建的表TB_User

--用户类 表脚本创建 for SQL SERVER
Create Table TB_User
(
ID int identity(1,1) primary key,
Name varchar(50) not null,
Birthday datetime
);


然后,我们通过PDF.NET实体类生成器,生成一个实体类User ,如下图:

单击“另存为”按钮,将生成的实体类文件保存下来,然后打开该文件:



/*
本类由PWMIS 实体类生成工具(Ver 1.1)自动生成
http://www.pwmis.com/sqlmap
使用前请先在项目工程中引用 PWMIS.Core.dll
2010-2-26 17:45:06

*/

using System;
using PWMIS.DataMap.Entity;

namespace MyNameSpace
{
[Serializable()]
public partial class User : Entity
{
public User()
{
TableName = "tb_user";
//IdentityName = "标识字段名";
IdentityName="ID";

//PrimaryKeys.Add("主键字段名");
PrimaryKeys.Add("ID");


AddProperty("ID", default(System.Int32));
AddProperty("Name", default(System.String));
AddProperty("Birthday", default(System.DateTime));
}


public System.Int32 ID
{
get{return (System.Int32)getProperty("ID");}
set{setProperty("ID",value );}
}

public System.String Name
{
get{return (System.String)getProperty("Name");}
set{setProperty("Name",value ,50);}
}

public System.DateTime Birthday
{
get{return (System.DateTime)getProperty("Birthday");}
set{setProperty("Birthday",value );}
}


}
}


1.1.1.2 实体查询
在创建了上面的实体类以后,便可以使用EntityQuery<T> 进行实体查询,例如如下代码:

Console.WriteLine("rn实体对象持久化测试:");

User zhang_san = new User();
//zhang_san.Uid = 5;
EntityQuery<User> query = new EntityQuery<User>(zhang_san,true );
zhang_san.Name = "张三1";
query.Save();// 新增
Console.WriteLine("新增实体对象OK");

zhang_san.Birthday = new DateTime (1977,3,10);
query.Save();// 修改
Console.WriteLine("修改实体对象OK");


注:EntityQuery<T>(T,true) 表示当前实体类的持久化方式为“新增”。

1.1.1.3 OQL实体查询语言
IN 查询

this.txtOQL.Text = "";

User u = new User();
OQL q = new OQL(u);
q.Select().Where(q.Condition.IN(u.Uid, new object []{1,3,5}));
this.txtOQL.Text += q.ToString()+"rn------------------rn";

q.Select().Where(q.Condition.IN(u.Name, new object[] { "张三","李四"}));
this.txtOQL.Text += q.ToString() + "rn------------------rn";


将输出:
SELECT *
FROM Tb_User
Where id IN(1,3,5)

------------------
SELECT *
FROM Tb_User
Where id IN(1,3,5) AND Name IN('张三','李四')

------------------

排序

q.Select().Where(q.Condition.IN(u.Uid, new object []{1,3,5})).OrderBy (u.Name ,"desc");


将输出:
SELECT *
FROM Tb_User
Where id IN(1,3,5)
Order by Name desc


TOP 选取前N行
设置 OQL的 TopCount 属性即可,注意目前只支持Access/SqlServer


OQL q = new OQL(u);
q.TopCount = 10;

q.Select().Where(q.Condition.IN(u.Uid, new object []{1,3,5})).OrderBy (u.Name ,"desc");


将输出:
SELECT Top 10 *
FROM Tb_User
Where id IN(1,3,5)
Order by Name desc

条件比较查询
LIKE
q.Select().Where(q.Condition.AND (u.Name,"Like","张%"));
大于等于
q.Select().Where(q.Condition.AND (u.Uid,">=",20));

注:可以使用Condition.AND/NOT/OR 三种逻辑表达式。
Condition
第一个参数是实体类属性;
第二个参数是比较符号,比如=,<>,>,<,>=,<=,Like 等;
第三个参数 是要比较的值。


最新的OQL支持Update,Delete语法了。


PFT_FundReviews p = new PFT_FundReviews();
OQL q = new OQL(p);
p.BankCode = "20";
p.FundCode = "KF001";
p.CityCode = "0210";

//修改语法
q.Update( p.CityCode,p.BankCode ).Where (p.FundCode );
//也可以使用下面的格式
// .Where(q.Condition .AND (p.FundCode ,"=",p.FundCode ));
Console.WriteLine("SQL=" + q.ToString());

// 删除语法
q.Delete().Where(p.FundCode);
Console.WriteLine("SQL=" + q.ToString());
Console.Read();



---------------------------------------------------------------------------------
OQL语法形式多样,使用灵活,类似SQL的方式,完全面向对象,避免运行时数据查询出现字段或表名称错误。

OQL扩展支持SQL聚合函数了


PFT_FundReviews p = new PFT_FundReviews();
OQL q = new OQL(p); //OQL实例定义
p.BankCode = "20";
p.FundCode = "KF001";
p.CityCode = "0210";
//调用OQL的统计函数
q.Select().Count(p.FundCode, "CountField1").GroupBy (p.BankCode ).OrderBy (p.BankCode,"desc" );
Console.WriteLine("SQL=" + q.ToString());
Console.Read();


-------------------------------------------------------------
执行代码,将输出如下结果:

SQL=SELECT BankCode,COUNT(FundCode) AS CountField1
FROM PFT_FundReviews
Group By BankCode
Order by BankCode desc

现在,OQL 已经可以支持Count, Max, Min, Avg等常用的聚合函数了,也支持分组查询。
至此,OQL已经扩展为支持基本SQL功能的全系列面向对象的数据查询语法了!

使用OQL的好处 :
--跟具体的数据库无关
--不需要精通SQL语言,语法更精炼
--完全面向对象,智能提示支持,避免运行时发生数据库表名称或者字段名称错误
--学习LINQ的桥梁



...全文
605 33 打赏 收藏 举报
写回复
33 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
bluedoctor 2012-10-23
框架最新版本已经开源,详细内容请看官网
  • 打赏
  • 举报
回复
anzhiqiang_touzi 2012-03-26
目前我也正在研究自己的ORM
原理我决定用PDF.NET份的原理,事物我用Spring.Net的原理
  • 打赏
  • 举报
回复
anzhiqiang_touzi 2012-03-26
[Quote=引用 30 楼 bluedoctor 的回复:]
引用 29 楼 faib920 的回复:
这个所谓的OQL,实际上就是一个QueryBuilder,没有多少价值

有没有价值看你怎么用,如果你就喜欢手工拼接SQL,那这个OQL真没有价值;如果你喜欢在VS IDE中像使用对象一样使用类似SQL的东西,并且可以避免写错SQL,那么就有价值了。
[/Quote]
兄弟你错了,PDF.net的思想很有研究价值的
现在很多框架做ORM都是反射的。Linq 有了运行时编译,比反射还慢
而:PDF.net架构是轻量级的。不用反射来做。
我没研究PDF.NET的事物机制
我觉得PDF.net如果把事物做成Spring.Net的方式就非常好了。
  • 打赏
  • 举报
回复
bluedoctor 2011-02-28
[Quote=引用 29 楼 faib920 的回复:]
这个所谓的OQL,实际上就是一个QueryBuilder,没有多少价值
[/Quote]
有没有价值看你怎么用,如果你就喜欢手工拼接SQL,那这个OQL真没有价值;如果你喜欢在VS IDE中像使用对象一样使用类似SQL的东西,并且可以避免写错SQL,那么就有价值了。
  • 打赏
  • 举报
回复
faib920 2011-02-26
这个所谓的OQL,实际上就是一个QueryBuilder,没有多少价值
  • 打赏
  • 举报
回复
jamesteo 2010-07-30
没有lambda表达式,查询真的很难看
  • 打赏
  • 举报
回复
bluedoctor 2010-05-03
结贴送分!
  • 打赏
  • 举报
回复
bluedoctor 2010-04-27
还有人顶就结帖了。
  • 打赏
  • 举报
回复
han_shen 2010-04-13
好东西
  • 打赏
  • 举报
回复
bluedoctor 2010-04-13
OQL提供了多种缺省的简单书写形式,如果要比较的条件是等于尸体对象自己的属性值,那么上面的表达式可以这么写:

PFT_FundReviews p = new PFT_FundReviews();
OQL q = new OQL(p);
p.BankCode = "20";
p.FundCode = "KF001";
p.CityCode = "0210";

OQLCompare cmp = new OQLCompare(p);
OQLCompare cmpResult = (cmp.Comparer(p.CityCode) | cmp.Comparer(p.BankCode))
& ( cmp.Comparer(p.FundCode) | cmp.Comparer(p.BankCode));

q.Select().Where(cmpResult);
Console.WriteLine("SQL=" + q.ToString());


  • 打赏
  • 举报
回复
wuyi8808 2010-04-13
看看先。
  • 打赏
  • 举报
回复
bluedoctor 2010-04-13
PDF.NET 3.5版本支持复杂比较条件表达式:


PFT_FundReviews p = new PFT_FundReviews();
OQL q = new OQL(p);
p.BankCode = "20";
p.FundCode = "KF001";
p.CityCode = "0210";

OQLCompare cmp = new OQLCompare(p);
OQLCompare cmpResult = (cmp.Comparer(p.CityCode, OQLCompare.CompareType.Equal, "021")
| cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"))
& (cmp.Comparer(p.FundCode, OQLCompare.CompareType.Equal, "KF008")
| cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"));

q.Select().Where(cmpResult);
Console.WriteLine("SQL=" + q.ToString());


执行,将输出下面的SQL语句:

SQL=SELECT *
FROM PFT_FundReviews
Where ( (CityCode=@CP1 OR BankCode=@CP2) AND (FundCode=@CP3 OR BankCode=@CP4) )



至此,OQL除了多表查询外,已经完全可以支持SQL中的查询方式!
当然,借助于LINQ,可以实现多表查询。


  • 打赏
  • 举报
回复
camperer 2010-04-12
好象以前看到过。。。
不过我觉得重复造轮子是不必要的,除非你的轮子比别人好得多。
  • 打赏
  • 举报
回复
I_Iverson 2010-04-12
linq不复杂,挺好用。

再者,3.5的发布不是问题,我用3.5开发的系统,部署到2.0框架机器上了
  • 打赏
  • 举报
回复
bluedoctor 2010-04-12
[Quote=引用 19 楼 i_iverson 的回复:]
linq不复杂,挺好用。

再者,3.5的发布不是问题,我用3.5开发的系统,部署到2.0框架机器上了
[/Quote]
现在还有很多人在使用VS2005,他们很难享受到LINQ的便利了。
虽然有点过时,也好像大家都说的,再重复发明轮子,但为啥还有人在用NHibernate,iBatis.NET呢?

存在既是合理的!

如果你连重复发明轮子的想法都没有,还有可能发明出一个更好的轮子吗?
  • 打赏
  • 举报
回复
xray2005 2010-04-11
学习下

顺便说一下 linq to entity 研究中
  • 打赏
  • 举报
回复
bluedoctor 2010-04-10
[Quote=引用 15 楼 ansiboy 的回复:]
才十块钱,还不如免费算啦。你以为便宜就能卖出???
[/Quote]

唐僧去西天取经,为啥佛祖不免费把经送给唐僧呢?
卖的不是价钱,而是诚心,否则,送给你等于是白送,你最终啥也学不到!
  • 打赏
  • 举报
回复
wjq 2010-04-10
对于只装了.NET 2.0的客户端,如果是Winform程序,直接把3.5和3.0的dll复制到程序目录就运行3.5的app了,如果是asp.net,毕竟是服务器升级下fx到3.5还是没啥问题的
  • 打赏
  • 举报
回复
ansiboy 2010-04-10
才十块钱,还不如免费算啦。你以为便宜就能卖出???
  • 打赏
  • 举报
回复
bluedoctor 2010-04-10
OQL的另外一种写法:

Sop_TodoList todolist = new Sop_TodoList();
return EntityQuery<Sop_TodoList>.QueryList(OQL.From(todolist)
.Select().Where(q.condition.AND(todolist.Lcjl_Username,"=",username)
.AND(todolist.Todo_date,"=",dt)
));



两行完成一个实体类的查询。
  • 打赏
  • 举报
回复
加载更多回复(13)
发帖
.NET技术前瞻

1.3w+

社区成员

.NET技术 .NET技术前瞻
社区管理员
  • .NET技术前瞻社区
加入社区
帖子事件
创建了帖子
2010-03-28 06:17
社区公告
暂无公告