6.查询
ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构,甚至可以屏蔽数据库之间的差异,以利于程序在不同数据库环境下的移植。
如一般的关系型数据库所具有的查询功能一样,Snake.Net框架也有着丰富的查询功能。当前版本的Snake.Net支持三种查询方式:查询构造器, OSQL查询语言和预定义的SQL语句。
(1)查询构造器
Snake.Net框架使用的是对象化的查询技术:将查询条件对象化,然后根据不同类型的数据库编写SQL语言解析器,将查询对象转化成对应的SQL语句,进行数据查询。
在Snake.Net框架内,可以使用查询构造器DataObjectQueryBuilder,通过添加特定的过滤条件、排序字段以及分页条件,构造查询对象,以实现简单功能的查询,请看演示代码:
IList employees;
DataObjectQueryBuilder builder;
builder = new DataObjectQueryBuilder(typeof(Employee));
using(IObjectManager om = ObjectManager.Create(typeof(Employee))){
builder.AppendCondition("FirstName", "Nancy");
employees = om.Query(builder);
}
(2)OSQL语言
OSQL语言是Snake.Net主要的查询方式。OSQL语言是一种类似于标准SQL语言的对象化、结构化的查询语言。Snake.Net可以通过不同的数据库解析器将OSQL语言转化为各自的SQL语言,因而使用OSQL语言查询也具有跨数据库系统查询的能力。
下面简单介绍一下OSQL语言,OSQL语言是一种面向对象的查询语言,由前缀和表达式组成(OSQL的前缀参见表
前缀 |
描述 |
Where:=, Condition:=, C:= |
过滤条件 |
Order:=, Sort:=, S:= |
排序条件 |
Page:=, P:= |
分页条件 |
表
逻辑运算符 |
描述 |
And, && |
过滤条件 |
Or, || |
排序条件 |
Xor, ^ |
分页条件 |
表
操作运算符 |
描述 |
! |
非 |
is empty |
是空值 |
is null |
是Null值 |
= |
等于 |
>= |
大于等于 |
> |
大于 |
< |
小于 |
<= |
小于等于 |
<> |
不等于 |
begin |
字符起始于 |
end |
字符结束于 |
contains |
包含特定字符 |
in |
包含特定值 |
between |
在两个值之间 |
表
下面我们看一句OSQL语句的范例及其使用的代码演示:
S:= Order.OrderDate Desc
P:=3-1
OSQL语言只需编写过滤条件、排序字段以及分页条件,至于对象与对象之间的关联关系,则全部由系统自动处理,对使用者来说是完全屏蔽的。接下来我们再看使用ObjectManager运行OSQL语句并获取查询结果的示例:
IList orders;
string expression;
expression = "ShipName = 'Ernst Handel' && " +
" (Product.ProductName begin 'e' || Product.ProductName begin 'c')" +
" S:= Order.OrderDate Desc" +
" P:=3-1";
using(IObjectManager om = ObjectManager.Create(typeof(Order))){
orders = om.Query(expression);
}
(3)预定义的SQL语句
所谓预定义的SQL,就是事先编写好查询使用的SQL语句,并选择设置一个或多个参数(参数的格式根据各个数据库驱动的特点格式略有不同,如Access数据库使用“?”表示,如果是MSSQL则用“@parametername”表示等等)。
Snake.Net支持在配置文件预先定义SQL语句,运行时传递名称和参数进行调用,返回查询结果。这些SQL语句可以是简单的单表查询,也可以是使用视图和存储过程的复杂查询。
Snake.Net的预定义SQL语句存放于配置文件中,请看演示代码:
<queryMapping name="OrdersQry">
SELECT OrderID, CustomerID, EmployeeID, ShipName
FROM [Orders Qry]
Where Country = ?
</queryMapping>
<queryMapping name="OrdersQry2">
SELECT OrderID, CustomerID, EmployeeID, ShipName
FROM [Orders Qry]
Where Country = ?
And ShipRegion = ?
</queryMapping>
<queryMapping name="OrdersQry3">
@@Orders
</queryMapping>
</queryMappings>
然后我们看一下在程序中如何调用预定义的SQL语句:
IList orders;
IObjectQueryManager qmm;
qmm = ObjectManager.Create(typeof(Order)) as IObjectQueryManager;
orders = qmm.QueryByName("OrdersQry", "France");
if (orders.Count > 0){
Console.WriteLine("Count:{0}", orders.Count);
for(int i = 0; i <orders.Count; i++){
Order order = orders[i] as Order;
}
}
qmm = ObjectManager.Create(typeof(QueryObject)) as IObjectQueryManager;
orders = qmm.QueryByName("OrdersQry2", new string[]{"Brazil", "SP"});
if (orders.Count > 0){
Console.WriteLine("Count:{0}", orders.Count);
for(int i = 0; i <orders.Count; i++){
QueryObject item = orders[i] as QueryObject;
Console.WriteLine(item[0]);
}
}
使用预定义的SQL语句,Snake.Net将根据参数直接运行定义的SQL语句,然后根据返回的数据,充填指定类型的对象。一方面由于是直接运行SQL语句不需要进行解析,所以它的运行效率是最高的,但另一方面预定义的SQL显然只能适用于特定的数据库,缺乏良好的移植性。