当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > .NET中容易混淆的几组重要概念

ASP.NET
FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用方法
.NET 常用功能和代码小结
在 .NET Framework 2.0 中未处理的异常导致基于 ASP.NET 的应用程序意外退出
asp.net IList查询数据后格式化数据再绑定控件
asp.net sql存储过程
asp.net 简单实现禁用或启用页面中的某一类型的控件
asp.net(c#)获取内容第一张图片地址的函数
The remote procedure call failed and did not execute的解决办法
ASP.NET 在线文件管理
asp.net 读取并修改config文件实现代码
ASP.NET Cookie 操作实现
asp.net Silverlight中的模式窗体
Silverlight中动态获取Web Service地址
asp.net Silverlight应用程序中获取载体aspx页面参数
asp.net 水晶报表隔行换色实现方法
asp.net 获取Gridview隐藏列的值
手动把asp.net的类生成dll文件的方法
asp.net 使用ObjectDataSource控件在ASP.NET中实现Ajax真分页
动态指定任意类型的ObjectDataSource对象的查询参数
asp.net Md5的用法小结

ASP.NET 中的 .NET中容易混淆的几组重要概念


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-23   浏览: 102 ::
收藏到网摘: n/a

许多朋友在学习和开发.NET程序的过程中经常发现一些误用.NET概念的情况。本文将对AJAX、LINQ、Lambda等相关的概念进行梳理,希望在明确这些概念之后,大家能够把注意力集中在对于具体问题的分析解决上,而不要让沟通成为瓶颈。

在这篇文章中,希望澄清三组概念,它们是:

AJAX / AJAX框架 / AJAX.NET (Professional) / ASP.NET AJAX

这是我见过的混淆最多的一组概念。不过当去年AJAX技术如火如荼,AJAX框架层出不穷,而微软又推出ASP.NET AJAX框架之后,这四个概念之间的混淆也愈发严重起来了。我经常能看到这样的问题:

◆我在用AJAX技术时不知道怎么在UpdatePanel里……
◆我用AJAX.NET框架调用Web Service时……

这是非常典型的概念混淆,上面两句话的AJAX与AJAX.NET都应该使用ASP.NET AJAX替换。关于这几个概念的区别我《深入浅出ASP.NET AJAX》系列WebCast多次进行解释,不过收效似乎并不明显。于是我打算在这里再进行一下说明:

AJAX是Asynchronous JavaScript and XML缩写。这个概念代表的是一种技术,当您在说“我在项目中使用了AJAX技术时”,只是代表了您使用客户端XMLHttpRequest对象与服务器端进行异步通信。不过因为随着AJAX技术的运用往往会带来丰富的客户端效果,因此对AJAX技术的广义理解也可以认为这是一种操作客户端DOM而带来丰富效果的技术(这个“广义”的描述其实并不准确,大家明白老赵的意思就可以了)。

AJAX框架是一套辅助开发人员使用AJAX技术的代码包(库,etc.)。一个AJAX框架的目的一般是对XMLHttpRequest对象的使用进行封装,并提供一些操作DOM元素或者实现特殊效果的“捷径”。成熟的AJAX框架有很多,它们可以被分为“以客户端为中心”和“面向特定服务器技术”两大类。前者的优秀代表有(排名不分先后):Prototype、jQuery、Mootools、YUI、Dojo等等(最后两个其实更接近一套客户端界面库,也就是“广义”的AJAX框架);而后者的典型代表既是AJAX.NET和ASP.NET AJAX了——当然,也有优秀的AJAX框架面向其他服务器技术,在此不提。

AJAX.NET (Professional)是ASP.NET平台上著名的AJAX框架,诞生于2005年2月(虽然正式命名为AJAX.NET则是在两个月之后),作者为Michael Schwarz。同年10月,Michael为AJAX.NET提供了更丰富的功能(主要是安全性方面),并将其改名为AJAX.NET Professional。AJAX.NET提供的最主要的(也是唯一)的功能就是异步调用服务器端方法,可谓非常纯粹的“基于数据”的AJAX使用方式。这个框架是一个个人作品,有支持.NET 1.1和2.0的版本,它并不属于微软官方,目前已经停止更新。

ASP.NET AJAX的Code Name为“Atlas”,在CTP向Beta版转移时曾经发生过翻天覆地的变化。ASP.NET AJAX中包含了UpdatePanel等控件,可以非常透明地为现有的ASP.NET WebForms应用程序添加AJAX效果。此外还提供了客户端异步调用Web Services的方法,使开发人员也能够使用面向数据的方式使用AJAX技术。值得一提的是ASP.NET AJAX的“附属品”相当丰富。例如ASP.NET AJAX名为“Microsoft AJAX Library”的客户端部分是一个纯客户端AJAX框架,提供了面向对象类型系统、浏览器兼容层、异步通信层等多种基础组件;ASP.NET AJAX的开源扩展包“AJAX Control Toolkit”包含了数十个可以直接使用的AJAX服务器端控件,这样开发人员能够轻松地添加丰富的客户端效果。同时,官方还为ASP.NET AJAX提供了“非正式”地扩展包,其中的History等优秀控件也将加入未来版本的ASP.NET AJAX框架中。ASP.NET AJAX是官方出品的AJAX框架,目前已经被集成到ASP.NET 3.5中去了,因此其版本号也从ASP.NET AJAX 1.0一下子“跃升为”ASP.NET AJAX 3.5。如果您看到了这些版本号也请不要疑惑,其实ASP.NET AJAX 3.5相对于ASP.NET AJAX 1.0来说只是修补了一些细小bug,几乎没有任何变化。

LINQ / LINQ to SQL / LINQ to XXX

LINQ是新生事物,不过从不少文章和讨论上看来,这方面的概念也已经有点混沌不清了。因此我们经常可以看到这样的话:

◆LINQ只能将数据表与实体属性一一对应……
◆LINQ开发指南:在LINQ中进行数据库字段映射……

以上两句话其实说的都是LINQ to SQL而不是指LINQ。可能由于LINQ to SQL的上镜率最广(连MSDN上About LINQ的第一个示例就是查询数据库的),因此许多人都将LINQ to SQL与LINQ混用,这会给初学者造成误解,认为LINQ就是LINQ to SQL,LINQ to SQL就是LINQ——事实当然不是这样的。

LINQ是Language-Integrated Query的缩写,是C# 3.0和VB 9.0中新加入的语言特性,可以在编程时使用内置的查询语言进行基于集合的操作。这么做可以大大简化开发过程,提高开发效率。例如:

以下为引用的内容:
List userList = GetUserList();
var userWithOddId = from u in userList
                    where u.UserID % 2 == 1
                    select u;
 
foreach (User u in userWithOddId)
{
    Console.WriteLine(u.UserName);
}

如果没有LINQ,要筛选出ID为奇数的User对象则需要创建一个List,然后遍历整个列表,将符合特定条件的User对象放入新列表。而有了LINQ,这部分的筛选就变得非常容易,甚至只需要一句话就能完成。如果觉得这个例子不够说明LINQ对生产力有重大贡献的话,请关注我接下来的一篇文章(暂定名为《我们为什么要拥抱LINQ》)。LINQ特指形如上面这段代码中from...where...select这样的用法,其返回值是IQueryable或IEnumerable。

LINQ to SQL是.NET 3.5内置的一个轻量级O/R Mapping解决方案,可以将数据表映射为实体对象,方便开发人员对数据库的操作。可见,LINQ to SQL实只是LINQ的一个实现,提供了一个可以查询SQL Server数据库的LINQ Provider。

LINQ Provider是LINQ查询的执行器,标准LINQ语法支持许多的操作符,但是某个具体的LINQ实现可能只支持其中的一部分。在.NET 3.5默认提供了三种LINQ Provider,分别是LINQ to Object(即上面的例子),LINQ to SQL以及LINQ to XML。

LINQ to XXX表示使用LINQ针对XXX这种数据进行查询的解决方案。我们可以自定义LINQ Provider,使用我们自定义的查询规则来处理特定数据集。目前互联网上已经可以找到数十种LINQ Provider(如LINQ to Flickr,LINQ to NHibernate等),而已经处于beta 3阶段的ADO.NET Entity Framework,最终也会提供一个LINQ Provider,叫做“LINQ to Entities”。

Lambda Expression / Expression Tree / 匿名方法

Lambda Expression从定义上讲是指带有“=>”符号的表达式,例如:

以下为引用的内容:
◆x => x + 1
◆(x, y) => x > y
◆() => 5
◆(x, y) => { return x > y; }

Lambda Expreesion本身并不会在概念上引起混淆,不过由于在C# 3.0中Lambda Expression有两种截然不同的使用方式,有些朋友就会产生疑问,究竟Lambda Expression是做什么用的?

Lambda Expression的一个重要作用就是提供一种使用匿名方法的新语法,在《您善于使用匿名函数吗?》一文中您可以看到这种使用方式。利用Lambda Expression表示匿名函数的一个重要的缺点就是无法使用带out或ref关键字的参数,不过它比使用delegate关键字的表示法略为简单一点,因为无需提供参数类型,例如:

以下为引用的内容:
public static bool CallMethod(Func method)
{
    return method(0);
}
 
static void Main(string[] args)
{
    CallMethod(delegate(int a) { return false; });
    CallMethod(a => { return false; });
}

可见,使用Lambda Expression表示的匿名方法无需指定参数类型,因为这一切都已经交给编译器来判断了。这一点在参数类型长而复杂的情况下(例如并行库中的方法)非常重要。因此现在要不是会涉及到out/ref参数,我都会使用Lambda Expression来表示匿名方法。

Lambda Expression的另一个作用自然就是构造一个LambdaExpression对象。任意一个Expression对象都表示了一个Expression Tree的根节点,而开发人员可以通过解析这个Expression Tree来实现特定的功能。我们编写的方法可以接受一个Lambda Expression作为参数,但是我们还必须对这个参数的形式进行限制,这个参数才能有意义。这时候我们就会使用Expression类型作为方法的参数类型,这样在使用这个方法时就必须使用满足TDelegate的签名及返回值的Lambda Expression才能编译通过。例如:

以下为引用的内容:
public static void CallMethod(Expression> prediect) { ... }
 
static void Main(string[] args)
{
    CallMethod(a => a > 0);
}

解析一个Expression Tree并不是一件简单的事情,一定程度上这相当于在进行编译工作,只是最终生成的结果不是机器码或IL,而是一个执行结果,并且语法解析的过程已经由C#编译器帮我们完成了。我在《扩展LINQ to SQL:使用Lambda Expression批量删除数据》一文中曾经提到过这一点,并且给出了一个实例,感兴趣的朋友们可以参考一下。

需要注意的是,如果在构造一个Expression对象时,Lambda Expression的Body部分不能是Statement;而在表示一个匿名对象时Lambda Expression的Body既可以是Expression也可以是Statement。无论是使用Expression还是Statement作为Body,只要表示的含义相同,编译器都会生成一样的匿名函数。例如以下两种写法其实是等价的:

以下为引用的内容:
◆(x, y) => x > y
◆(x, y) => { return (x > y); }

最后,我留给大家一个问题:以下两个做法的结果是相同的,而代码也非常接近。不过它们其实有着非常大的区别,您能指出吗?

以下为引用的内容:
var intList = new List() { 1, 2, 3, 4, 5 };
foreach (int i in intList.Where(i => i % 2 == 1))
{
    Console.WriteLine(i);
}
 
var intList = new List() { 1, 2, 3, 4, 5 }.AsQueryable();
foreach (int i in intList.Where(i => i % 2 == 1))
{
    Console.WriteLine(i);
}