LINQ to SQL系列Part 9-Using a Custom LINQ Expression with the control

LINQ to SQL系列Part 9-Using a Custom LINQ Expression with the <asp:LinqDatasource> control

本文英文原版:
http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx

在本系列的Part 5部分,我提到了.NET 3.5里新引入的<asp:LinqDataSource>控件,利用它我们可以轻易的将ASP.NET UI控件绑定到LINQ to SQL数据模型.在另一篇有关<asp:ListView>控件的文章里(Part 1 - Building a Product Listing Page with Clean CSS UI),我多多少少演示了其用法.

在这些文章里,我执行的查询都是比较直观的(其where子语句都是处理单个表的数据),今天的文章,我将演示如何基于LinqDataSource控件来使用的比较全的LINQ查询表达式,以及任意的LINQ to SQL查询表达式.

Quick Recap: <asp:LinqDataSource> with a Declarative Where Statement

在本系列的Part 1 和 Part 5部分,我演示了如何利用LinqDataSource控件内置的条件过滤功能,来对某个LINQ to SQL数据模型进行限制.

比如,假定我们已经为Northwind数据库创建了一个LINQ to SQL数据模式(具体过程可参考Part 2部分),我们可以在页面上添加一个<asp:LinqDataSource>控件,并设置一个<where>过滤条件,仅仅返回某个指定category的所有产品(通过指定"categoryid"的值):

图1

然后我们可以将一个<asp:gridview>控件指向该数据源,并启用分页、编辑、排序功能,如下:

图2

当我们运行上述页面的时候,这个基于Product数据模式的GridView将自动的支持排序、分页、编辑功能.

图3

像上面一样显式地使用<where>参数,在大多数情况下没有问题。但是如果我们想使过滤条件更为复杂一些呢?比如,我们想动态的设置countries,而只将这些国家的产品显示出来,这么办呢?


利用<asp:LinqDataSource>控件的Selecting事件

为了处理用户定制查询,你可以构建一个事件处理器来处理<asp:LinqDataSource>控件的"Selecting"事件.在该事件处理器里你可以任意地写代码,以检索你想要得到的结果.为此,你可以利用一个LINQ to SQL查询表达式, 或调用一个存储过程,或使用一个Custom SQL Expression(用户定制查询),以对该LINQ to SQL数据模型进行检索.一旦你检索到了一连串的数据(a sequence of data),你需要做的就是将其赋值给一个LinqDataSourceSelectEventArgs对象的"Result"属性.然后,<asp:LinqDataSource>控件将对这一连串的数据进行处理.比如,如下是一个LINQ to SQL查询表达式,它将指定国家的产品检索出来:

VB:

图4

C#:

图5
注意:你没有必要在事件处理器里写具体的查询语句,相反你可以将具体的查询语句封装在一个helper method方法里,然后在事件处理器里直接调用即可.在Part 8的前面部分我演示了如何来创建这种helper method(比如GetProductsByCategory helper method)

现在运行页面,你将只会看到指定国家的产品:

                    图6

以上很酷的一点需要引起我们的注意,那就是分页和排序依然基于GridView——即使我们使用一个用户自定义的Selecting事件来检索数据.而分页和排序其实发生在数据库端——这就意味着我们只需要根据GridView里当前页面的page index索引,仅仅从数据库检索出10条产品信息即可(这样就大大的提高了效率)

你可能要问,就算我们使用了自定义selecting事件,我们又这么可能得到高效的分页和排序功能支持呢?答案在于LINQ使用延缓执行模式(deferred execution model)——就是说,在你对结果反复进行操作完成之前,查询没有真正的执行过.这种延缓执行模式的好处之一在于:你可以构建精细的查询(nicely compose queries),更多信息请参阅Part 3部分.

在上面的"Selecting"事件处理器里,我们声明了一个自定义的LINQ查询,然后对"e.Result"属性进行赋值.不过我们还没有真正的执行它(因为我们还没有遍历结果或调用ToArray() 或 ToList()方法). LINQDataSource对查询自动地运用Skip()和Take(),同时运用一个"orderby" expression——根据GridView控件的page index和sort preference(即跟据什么来排序),来对这些值自动的进行运算.然后LINQDataSource执行LINQ查询并返回数据. LINQ to SQL将确保分页和排序逻辑是发生在database端,仅仅要用到的那10条产品记录被返回.

注意下面,我们又是怎样使用GridView来编辑和删除产品的:

图7

只要我们的Selecting事件指派了这样的一个Result query——其结果集(result sequence)是规则的实体对象(比如Product, Supplier, Category, Order等),那么编辑/删除功能就得到很好的支持,LINQDataSource会自动的进行处理.

关于使用LINQ to SQL进行updates操作的更多内容,请参阅Part 4部分,关于使用LinqDataSource来进行Updates实际操作的示例,请看Part 5部分.


在Selecting事件里执行Custom Query Projections

LINQ强大之一在于它可以定制"shape" 或 "project"数据.你可以在一个LINQ to SQL表达式里指出你仅仅想从结果里返回一个子集.关于这方面的更多内容请参阅Part 3部分.

比如,我们想修改"Selecting"事件处理器,使GridView显示产品的指定信息.我们想将显示ProductID, Product Name, Product UnitPrice, the Number of Orders(产品的订购量),以及总的Revenue之和.对后两项我们可以使用如下的LINQ expression,如下:

VB:

图8

C#:

图9

注意:上述Revenue声明里用到的Sum方法是Extension Method的一个范例,而它使用的函数又是Lambda expression的一个范例.而结果类型是一个anonymous type(匿名类型)——因为它的类型是由查询表达式推断出来的.Extension Methods, Lambda Expressions, 以及Anonymous Types都是VS 2008里VB 和 C#的新语言特性.

当把结果绑定到GridView后,UI看起来和下面的差不多:


图10

注意,在GridView里分页和排序依然工作正常——即使我们使用的是自定义的LINQ shape/projection数据. 

与自定义shape/projection不太协调的是,它不支持inline editing.因为我们在Selecting事件里使用了一个custom projection,因此LinqDataSource没有办法确切的知道如何更新实体对象.如果我们要对使用shaped类型数据的GridView添加编辑功能,要么转而使用ObjectDataSource控件(我们可以在里面提供定制的Update方法来来处理updates),要么把用户导航到另一个页面执行更新——比如将一个DetailsView 或 FormView控件绑定到一个Product实体以进行更新.

总结:

利用LinqDataSource内置的显式过滤功能,我们可以很容易地对一个LINQ to SQL数据模型执行常见的查询操作.

要实现更高级点的或用户自定义过滤条件,我们可以利用LINQDataSource的Selecting事件.我们可以在该事件里执行对LINQ to SQL数据的过滤和检索的任何逻辑.你可以调用方法来检索数据,使用LINQ Query Expressions,调用存储过程或调用一个Custom SQL Expression来实现.

希望这些对你有所帮助!

Scott

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值