OQL and O/R Mapping

思维 - 现实 - 思维

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  8 随笔 :: 0 文章 :: 77 评论 :: 0 引用

本系列教程将全面介绍 oql.net ,包括 selectinsertupdate delete 语句,也包括 selectfromjoinonwheregroup byhavingorder by case 子句。

本系列教程将以 Microsoft SQL Server Northwind 数据库为基础并采用 C# 来写示例代码,有关在 VB.NET 等其他语言中使用的注意事项将在相应的地方进行说明。

1Select单表的全部字段

Select 语句是我们最为常用的 SQL 语句,也是 DML 中最复杂的语句,就让我们从最简单的 select 语句开始吧:

-- SQL 1

SELECT [Orders].*

FROM [Orders]

WHERE

  [Orders].[EmployeeID] = 5 AND

  [Orders].[ShipVia] = 1

上述 sql 语句直接翻译为 oql 是这样的:

// OQL 1

SelectQuery query = OQL

  .Select(NW.Order)

  .From(NW.Order)

  .Where(NW.Order.EmployeeID == 5

    && NW.Order.ShipVia == 1);

从这种简单的翻译我们不难看出,在 oql.net 中,oql 的书写形式和 sql 惊人的相似。

代码中的NW 表示 Northwind 数据库的架构名称,这个名称用来区分于其他的架构。oql.net 允许您在一个程序中同时使用多个数据库架构,这些架构既可以是不同的数据库,也可以是同一个数据库的多个子架构。我们建议将一个较大的数据库按照业务模型划分为多个子架构,这些子架构既可以重叠,也可以完全不同。

因为 SQL 1 是查询一个表的全部字段,属于最简单的 SQL 了,OQL 1 可以简化如下:

// OQL 1-2

SelectQuery query = OQL

  .SelectWhere(NW.Order.EmployeeID == 5 && NW.Order.ShipVia == 1);

 

2Select单表的部分字段

很多时候我们只需要 select 表中的某几个字段,比如下面的 sql

-- SQL 2

SELECT

  [Orders].[OrderID] , [Orders].[OrderDate] , [Orders].[RequiredDate]

FROM [Orders]

WHERE

  [Orders].[EmployeeID] = 5 AND

  [Orders].[ShipVia] = 1

翻译为 oql 如下:

// OQL 2

SelectQuery query = OQL

  .Select(NW.Order.OrderID, NW.Order.OrderDate, NW.Order.RequiredDate)

  .From(NW.Order)

  .Where(NW.Order.EmployeeID == 5 && NW.Order.ShipVia == 1);

Oql.net 的级联表达式是很灵活的,下面的 OQL 等同于 OQL 2。方法“_”也可以用“Add”,特别是在 VB.NET 中由于单个下划线不能作为标识符只能使用 Add 方法。

// OQL 2-2

SelectQuery query = OQL

  .Select(NW.Order.OrderID)._(NW.Order.OrderDate)._(NW.Order.RequiredDate)

  //.Select(NW.Order.OrderID,NW.Order.OrderDate).Add(NW.Order.RequiredDate)

  .From(NW.Order)

  .Where(NW.Order.EmployeeID == 5 && NW.Order.ShipVia == 1);

 

3、动态构造 select 子句

下面的 oql 等效于 OQL 2,所不同的是 OQL 2-3 select 子句是动态构造出来的,请注意在 VB.NET 中方法“_”用“Add”代替。

// OQL 2-3

ScalarList selectList = new ScalarList();

selectList.Add(NW.Order.OrderDate);

selectList.Add(NW.Order.RequiredDate);

 

SelectQuery query = OQL

  .Select(NW.Order.OrderID)._(selectList)

  .From(NW.Order);

  .Where(NW.Order.EmployeeID == 5 && NW.Order.ShipVia == 1);

其他子句的动态构造,将在相应的部分作介绍。

 

4、使用子查询

下面是一个使用子查询的 sql 语句:

-- SQL 3

SELECT [Orders].*

FROM [Orders]

WHERE

  [Orders].[CustomerID] IN

    (

      SELECT [Customers].[CustomerID]

      FROM [Customers]

      WHERE

        [Customers].[ContactTitle] = 'Owner'

    )

直接翻译为 oql 如下,形式依然和 sql 极其相似:

// OQL 3

SelectQuery query = OQL

  .SelectFrom(NW.Order)

  .Where(

    NW.Order.CustomerID.In(OQL

      .Select(NW.Customer.CustomerID)

      .From(NW.Customer)

      .Where(NW.Customer.ContactTitle == "Owner")

)

);

oql 语句较长时把子查询抽出来更有利于维护和重用,这有点像重构。下面的 OQL 3-2 等效于 OQL 3

// OQL 3-2

SelectQuery sub = OQL

  .Select(NW.Customer.CustomerID)

  .From(NW.Customer)

  .Where(NW.Customer.ContactTitle == "Owner");

 

SelectQuery query = OQL

  .SelectWhere(NW.Order.CustomerID.In( sub ));

当表间的约束条件作为子查询的条件时,可以使用对象表达式简化 oql 语句。本例的 Orders 表和 Customers 表是父子关系,通过 CustomerID 进行关联,简化后的 oql 如下:

// OQL 3-3

SelectQuery query = OQL

  .SelectWhere(NW.Order == (NW.Customer.ContactTitle == "Owner"));

对象表达式使得 oql 语句变得更简洁,但同时也降低了可读性。

 

有关 where 子句及多表查询将在随后陆续介绍。

posted on 2006-09-21 02:09 Kimphi 阅读(1350) 评论(14)  编辑 收藏 网摘 所属分类: OQL.NET

评论

#1楼 2006-09-21 08:28 LEK[未注册用户]
没有LinQ方便
  回复  引用    

#2楼[楼主] 2006-09-21 09:06 Kimphi      
@LEK
Linq 现在是预编译,未来会集成到语言中,确实比较方便。

但是 DLinq 目前的规范中只支持 Select ,而 SQL 并不仅仅是 Select 语句,所以说 DLinq 是一种 Select 替代方案而不是 SQL 替代方案。

  回复  引用  查看    

#3楼 2006-09-21 09:28 OOP      
恩,看看。
  回复  引用  查看    

#4楼 2006-09-21 09:31 progame      
SelectQuery query = OQL

.SelectWhere(NW.Order == (NW.Customer.ContactTitle == "Owner"));


我希望是
EntityList<Order> list = OQL.Where(NW.Order.Customer.ContaintTiltle == "Owner")

还有对于返回的非entity的结果集 如何访问

还是用 ["OrderDate"] 还是用 [NW.Order.OrderDate]?
对于组合的表达式怎么办? 如 A + (B -C)后生成的fieldname如何访问?

  回复  引用  查看    

#5楼[楼主] 2006-09-21 09:52 Kimphi      
@progame
像 NW.Order.Customer.ContaintTiltle == "Owner" 这种关系路径看起来似乎简便,v1.0(未发布)便有,但会带来其他问题,比如一个表在查询语句中多次使用等,不排除下未来版本能解决。

另外,oql.net 是独立的查询方案而不是一个 O/R Mapping 方案,NObject 则是一个包含 oql.net 的 O/R Mapping 框架。NObject 的 ObjectSet 不仅仅是 List 那么简单,它提供了使用 oql 进行查找、筛选、排序等附加功能。

A + (B - C) 生成的 field,在 v1.0 是通过一种 as 方案来实现的,在 2.0 中移除的原因是 C# 2003 和 C# 2005 的 IDE 的 Intellisence 在处理重载时有问题导致无法上下文提示(VB.NET 则无此问题),即将发布的 v3.0 中将有完善的方案。

  回复  引用  查看    

#6楼 2006-09-21 10:34 progame      
第一个问题很难控制住的 还是写查询的人自己来决定 我明白你的顾虑,比如说NW.Order.Customer + NW.Customer.Code 这样就乱套了

关于NObject,我看了刚才,不错的解决方案,尤其是批量更新的处理,我还是觉得不需要在程序中集成太复杂的SQL,,我上面的EntityList其实就是你的ObjectSet

对于是否延迟加载大对象,子记录集,我觉得应该可以给用户选择权,因为表设计中,我会把大对象分表存放的,有时候的处理子记录集是需要一次加载的,如果是SQLSERVER,支持多条SQL提交时,可以减少数据交互次数的

对于复杂查询,一般就会涉及到函数处理了(不仅仅是聚合函数),我的解决方案是用简单的通过你这种方式去构造SQL,复杂的移到XML或者是存储过程去处理,数据库平台无关性通过转换层去处理

  回复  引用  查看    

#7楼[楼主] 2006-09-21 10:54 Kimphi      
@progame
第一个问题是:比如 select …… from orders a, orders b

你说的数据处理方式和我们的并不矛盾。代码中用不用复杂的查询,由使用者决定而不是框架决定。成功的 o/r mapping 都提供了或是字符串的或是强类型的 oql 方案,正体现了用户的需求和选择权。

  回复  引用  查看    

#8楼 2006-09-23 23:48 Edward.Net      
怎么越看越像我们公司一年就在项目开发中使用的东西,刚开始觉得挺神奇的。
  回复  引用  查看    

#9楼[楼主] 2006-09-24 09:48 Kimphi      
@Edward.Net
呵呵,很多东西看起来很相似的

  回复  引用  查看    

#10楼 2006-09-28 16:57 Laser.NET      
请问对于SQL中给表和字段取别名的"AS"关键字在 OQL.NET中如何支持?
  回复  引用  查看    

#11楼[楼主] 2006-09-28 17:25 Kimphi      
@Laser.NET
oql.net 1.0 提供了一种 as 方案,但在 2.0 中移除了,原因是 C# 2003 和 C# 2005 的 IDE 的 Intellisence 在处理重载时有问题导致无法上下文提示(VB.NET 则无此问题),即将发布的 v3.0 中将有完善的方案。

  回复  引用  查看    

#12楼 2007-01-09 14:08 DF[未注册用户]
Dim om As New ObjectManager(DatabaseType.Oracle, ConnectionType.OleDb, "Provider=OraOLEDB.Oracle.1;Password=ps;Persist Security Info=True;User ID=user;Data Source=DF")

Dim orders As New DataSet

om.BeginTransaction()

'以下语句执行时报错:方法不能执行
orders = om.GetDataSet("select * from t")

请大侠解释一下!非常感谢!
我的QQ:68031608 cs_wangwei_cs@hotmail.com

  回复  引用    

#13楼 2007-01-09 14:38 DF[未注册用户]
--!似乎这个帖子,时间比较久远了(2006-09-28 17:25)……
  回复  引用    

真他妈是个渣滓东西,除了能实现ORM外,代码长得比SQL更恐怖
  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 510232




相关文章:

相关链接: