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