The wind call my name

用知识和思考来丈量世界
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

LINQ的数据库查询应用

Posted on 2007-07-01 21:40  徐鸿翼  阅读(2100)  评论(2编辑  收藏  举报

今天看到了ScottGu在其博客上发布了LINQ to SQL的第三部分LINQ to SQL (Part 3 - Querying our Database),自己也载到了Visual Studio 2008 Beta1版,结合自己的实际学习操作,翻译整理一下。

Northwind数据库使用LINQ设计器建模

通过以前的学习,我们已经知道如何使用Visual Studio 2008内置的用于LINQ to SQL设计器创建类模型。下面就是所创建的Northwind数据库类模型:

linq3_step1

检索产品

一旦我们定义好数据模型类,就可以非常简单的从数据库中查询和检索数据。LINQ to SQL可以通过编写LINQ语法来对使用设计器创建的NorthwindDataContext类进行查询操作。例如,要检索和迭代一系列产品对象,就可以这样编写代码:

linq3_step2

在上面的查询中使用了“where”LINQ查询语法子句来返回一个指定类别的产品集,这里是使用CategoryID执行的筛选。 但是,在查询数据时LINQ to SQL还拥有大量的灵活性,可以利用建模中定义的关系关联来执行更丰富、更自然的查询操作。例如,可以修改上面的查询,以通过CategoryName筛选取代通过Categroy筛选,代码如下:

linq3_step3

注意上面的查询中如何使用在每个Product对象上的Category属性通过Product所属类别的名称来进行数据筛选。这个属性是由LINQ to SQL自动创建的,因为我们根据数据库建模的Category和Product类之间存在一对多关系。下面是使用数据模型关系关联进行查询的另一个例子,只检索在订单中出现5次以上的产品集,其中OrderDetails集合同样是LINQ根据数据模型中关系关联自动创建的:

linq3_step4

在调试器中LINQ to SQL的可视化查询 

当执行查询或更新对象模型的时候,像LINQ to SQL这样的对象关系映射者会自动创建和执行适当的SQL代码。对于ORMs比较陌生的开发者最关心/顾虑的问题之一是“它到底实际执行了什么样的SQL代码呢?”。好消息是,当使用调试器运行应用程序时可以十分简单的看到实际的SQL代码:

linq3_step5

实际SQL代码如下:

linq3_step6

从Visual Studio 2008 Beta2开始,就可以使用一个新的LINQ to SQL可视化插件来更容易地查看和测试任何LINQ查询表达式(可惜微软现在还没发布Beta2)。下面是作者原文中展示的可视化操作:

linq3_step7

linq3_step8

绑定LINQ to SQL查询结果到ASP.NET控件

 LINQ查询返回的是实现IEumerable接口的结果集,这正是ASP.NET控件用于绑定对象支持的接口。所以,可以绑定任何LINQ,LINQ to SQL,或者LINQ to XML查询结果集到ASP.NET控件。

例如,可以在aspx页面中定义一个GridView:

linq3_step9

然后在代码中绑定LINQ to SQL查询结果集到GridView:

linq3_step10

生成页面如下:

linq3_step11

查询结果构形

在上述产品查询中,我们默认检索了Product实体类中映射的所有列的数据:

linq3_step3

但常常我们只需要返回每个产品的一个子集。这时我们就可以使用LINQ和C#、VB编译器所支持的数据构形特性,通过修改LINQ to SQL查询来只返回数据的一个子集:

linq3_step12

返回的数据子集结果如下:

linq3_step13

LINQ to SQL更酷的是,当构形数据时可以充分利用数据模型类的关系关联,来表达真正有用和高效的数据查询。例如,下面的查询从Product实体中检索ProductID和Name,包含该Product的Order总数,以及每个Product在所有订单中的价格总和:

linq3_step14

LINQ to SQL转换的实际执行的SQL如下:

linq3_step15

返回的数据集结果如下:

linq3_step16 

需要注意的是,在上面的例子中使用了对象初始化器定义了一个匿名类型,来构形和定义结果结构。当处理这些匿名结果集时,在Visual Studio 2008中同样提供了完整的智能感知,编译检验和重构支持:

linq3_step17

查询结果分页

在Web应用中一个常见的需求是高效地建立数据分页UI。LINQ内置提供了两个扩展方法使得这项工作既简单而又高效——Skip()和Take()方法。下面我们使用这两个方法,通过指定参数返回只想要显示的10个Product对象,如果连接的数据库是SQL Server 2005,LINQ会使用ROW_NUMBER()函数进行分页操作:

linq3_step18 

需要注意的是,这里并没有在初始化products查询定义上添加Skip()和Take(),而是在随后绑定数据时添加的。这就引出一个问题“是否这就意味着查询先从数据库中抽取了所有数据,而后又进行的分页呢(不好的做法)?”。不,原因是LINQ使用了延迟执行模型——只有当结果集真正被使用时,查询才会被真正执行。延迟执行模型优点之一是可以方便跨过多个代码块来组合查询语句,提高代码的可读性。同样地,也可以在其他查询语句之外组合查询语句,提高了查询编写的灵活性和重用性。

定义BindProducts()方法后,就可以通过QueryString传入起始行索引,在GridView中分页显示products结果集:

linq3_step19

linq3_step20

总结

几个关键点:

1.灵活运用LINQ的关系关联建模和数据构形特性,定制所需的查询结果。

2.LINQ是延迟执行的,只有在结果真正被使用时,查询才会被执行。可以灵活组合查询语句,提高代码重用。

3.Visual Studio 2008中的LINQ to SQL可视化调试插件,在Beta2中才提供@_@