[教程]加快Flex应用运行速度的5种方法

mikel阅读(792)

作者 Jon Rose译者 张龙 发布于 2008年5月31日 下午9时5分

社区
Java
主题
RIA,
Web 2.0,
富客户端/桌面
标签
Adobe,
Flex,
Adobe集成运行时/AIR,
Flash

Jun Heider在O’Reilly的InsideRIA站点上发表了一篇精彩的文章,该文章就如何加快Flex应用的启动速度提出了很多建议,以帮助用户减少看见讨厌的“Loading”对话框的出现时间。他深入探讨了问题的不同方面,并对每种技术的优势和劣势进行了评判。

  1. 从外部加载媒体(Media)
    Heider提到了一个常用的Flex最佳实践——限制嵌入到应用/SWF文件中的媒体的数量,如图像、影片及mp3等资源都可以从外部的SWF文件加载。
  2. Flex框架可以直接将图片、mp3及字体等资源编译到SWF中。当你想让最终用户获得全部资源时,这种方式确实能派上用场,但是这会导致你的应用长时间停留在“Loading”阶段。 

  3. 在嵌入式字体中限制字符集
    Heider建议在嵌入式字体中限制字符集以降低SWF文件的总下载时间:
  4. 当你在Flex中嵌入一种字体时,你就会获得该字体的全部字符的支持。尽管这可能是你想要的,但你确信你需要全部字符么?例如,在一个只面向英文的应用中,你确信你真的想花时间下载中文字符数据么?

  5. 缓存框架
  6.         Heider回顾了Flex 3 support for runtime-shared-libraries (RSL)这篇文章:

    从Flex 3开始,你可以将Adobe签名的框架——RSLs缓存到Flash Player的cache中。这有两个好处。首先,缓存在Flash Player cache中的签名的框架RSLs可由所有配置好的Flex应用共享。换句话说,如果某人的应用已经下载了500k的签名的框架RSL,并且该RSL仍旧 在Flash Player cache中,那么你的应用就可以使用缓存下来的RSL。其次,即使某人清空了其浏览器缓存,对Flash Player cache也没有任何影响。

  7. 考虑模块化
  8. Heider谈到了将Flex应用划分成模块的好处:

    减少字体加载时间的另一种方式就是将你的Flex应用划分成模块。使用模块的一个好处在于当加载和卸载模块时你能完全操控它。



    之 所以要划分成模块的最后一个原因是他们更快,而且我能即时加载它们。换句话说,在启动时唯一需要加载的模块就是 Step1.swf模块。因此,在使用模块的情况下,最终用户节省了启动时间,但是当他从一个模块切换到另一个模块时却需要花更多时间,因为每个模块都需 要以JIT形式加载。在我的应用中,只有当用户首次在steps 1-5之间切换时需要花更多时间。

  9. 推迟实例化
  10.         Heider围绕着Flex组件的“creationPolicy”属性及何时实例化应用的不同部分给出了很多建议。

    如果你想减少从数据下载到用户真正可以使用的总时间,当务之急就是推迟实例化。这项技术背后的理念就是直到应用真正使用的时候才在内存中创建对象。

    尽管推迟实例化技术会在应用的整个使用过程中导致少许——通常不那么明显——的延迟,但与长时间的启动延迟相比,它还是可接受的。推迟实例化的另一个好处在于内存使用的优化。

Heider还谈到了一个“实验性”的条款——“使用流”,这是他在讨论Dirk Eismann的帖子(Building monolithic Flex SWFs that still startup quickly.”)时谈及的。Eismann提出一项技术以利用Flash Player中的多个frames以在部分应用中达到流的目的。查看所有的帖子以更多地了解该技术及关于加快Flex启动速度的建议。

查看英文原文:Top 5 Ways to Reduce Flex Application Startup Time

[教程]ASP.Net MVC中HtmlHelper类的应用

mikel阅读(731)

发现MVC没有沿用ASP.NET的自带控件,而是完全利用HtmlHelper类封装了Html常用组件,这样让ASP.NET的什么生命周期、运行时状态、等等都无效了,google了一下,发现个老外的教程
正在研究ing….,不过感觉MVC我可以不用了,我怎么越来越讨厌封装,动不动dotnet就给你封装这个封装那个,感觉完全就是在被别人做好的东西来搭建程序,完全没有创意可言,痛苦
好了,继续研究ing….
老外的地址:
http://blog.wekeroad.com/2007/12/05/aspnet-mvc-preview-using-the-mvc-ui-helpers/

[应用]WorkDay应用Flex实现ERP

mikel阅读(2079)

Workday takes ERP software
into the RIA space

by Julie Campagna

Articles this issue

When you think of RIA (rich Internet applications), you might think of Flash, Flex, Web 2.0, and the hipster of the web: all those social networking sites and applications like Facebook or Buzzword. The last thing that probably comes to mind is the stodgy corporate world of ERP (enterprise resource planning) software. Workday, Inc. is changing that.

Dave Duffield, cofounder and former chairman of PeopleSoft, founded Workday in 2005. This time around, Dave decided to do a whole new take on ERP software. The first big change was the delivery model: Software as a Service (SaaS) instead of traditional in-house installations. The next big change is the departure from relational databases for an in-memory system. Lastly, the traditional user interface is replaced by a richer, more immersive web application.

This article covers only the last aspect, the UI. After learning why Workday went with an RIA platform starting with Ajax, then moving to Flex, you'll learn about Workday's unique style of generating their UI. While some ERP vendors have over 100,000+ screens making up their UI, Workday has none. They merely build Flex components and dynamically create screens on the fly. Lastly, you'll find out how this proven innovator in the ERP realm supports today's corporate warriors outside their RIA application.

Why RIA?

Michael Bonadio, manager of the Workday UI team, said, "There are three things that are important to us: 1. Keep it simple and intuitive. 2. Work the way our customers work. 3. Keep it cool. It was these three things that drove us to RIA technologies." The richness of Ajax and Flex applications is what helps Workday achieve its mission: to provide a productive and pleasing user experience while differentiating the Workday product line in the marketplace.

Workay's application

Workday's application

"We started out with an Ajax front end. However, as we started to move towards larger and larger data sets, we found that it was difficult with Ajax. That's when we began to investigate Flex. After our first few experiments, we knew Flex was for us and we never looked back," Michael added. The Flex framework is a collection of classes, widgets, and effects. Flex provides two main benefits for Workday: portability and extensibility.

When you're a SaaS vendor, portability is important. You have to be able to support many different systems with countless configurations. There could be a Windows machine running Internet Explorer or a Mac running Safari; you just don't know. Workday's Ajax version of their application only ran on Internet Explorer 6.0. Granted, this was by design and not a limitation of the Ajax technology itself. Had they continued with Ajax for the next version, they would have chosen a library (or created their own) that would have supported multiple platforms. During the exploration phase for version 2, the desire for performance and a quick path to richness once again pointed to Flex. The beauty of the Flex version is that it utilizes Adobe Flash Player, the world's most pervasive software platform. The portability of Flex code meant that Workday went from supporting one version of one browser on one OS to supporting numerous platforms of various configurations — with no extra effort.

Extensibility is the other big factor of Flex that Workday found attractive. The Flex framework is an extension of the Flash platform. The key to the Flex platform is components. The components in Flex either inherit properties from another or are created by grouping a few components into one. Components, it turns out, fit perfectly into how Workday creates their application. Unlike traditional ERP applications, Workday does not have one hard-coded screen or form.

How do they do it?

How does an ERP system not have screens or forms? By definition, this is a system that presents forms to users for logging their vacation time, purchasing office supplies, or managing their company's employee base. With all the possible configurations and tasks, it's easy to see how ERP systems can have over 100,000 screens and forms. Keeping track and managing all those screens would be a nightmare. It is for that exact reason that Workday decided not to hard-code any of the UI for its screens.

Workday's system basically has three parts. There's the back end that keeps all the data and logic, called the OMS. Next, there is a UI server that makes requests to the OMS for data and then transforms the responses from the OMS into a homegrown description language. Lastly, there's the Flex application that interprets this meta-language and creates the screens on the fly. An easy way to think of the Workday application is that of a Flex virtual machine. The UI server gives the data and general layout in XML, then Workday's Flex app puts them both together to create a screen.

Workday's Navigator Tool

Workday's navigator tool

This is why component building works so well for Workday. While traditional Flex applications have hard-coded pages and forms made up of Flex components, Workday's doesn't. The only thing Workday's Flex developers build are more widgets for the virtual machine to process. The beauty of this is that a form can change over time, but the basic widgets that make up the form stay the same. Therefore, the UI developers don't get bogged down with form change requests. Whereas many Flex developers have to spend their time closing tickets that say things like, "Move name field down 3 pixels" or "Swap layout of Form A to match layout of Form B," Workday's developers don't have to bother with such trifles. Instead, they're left to innovate the advanced widgets that make up the future of ERP software.

Workday's Prompt Widget

Workday's prompt widget

Working outside the UI

Today's working professionals have many tools on their belts (sometimes literally). Aside of the standard desktop, you have laptops, BlackBerry devices, Apple iPhones, and more. People want to be connected 24/7 to their business. Workday is more than willing to help them stay connected.

The application already supports RSS feeds for staying updated on changes to your data. You subscribe to the feeds just as you would a blog or podcast; when the data changes, your feed gets updated. Many of the reports inside the Workday application support web services (REST or SOAP). This allows the customers to create and utilize mashup technologies. Whether it's posting jobs and having people apply inside of Facebook or creating a Google Map with all the branch offices mapped out, web services allow the users to make use of their data that in the past was stuck behind company (fire)walls.

Workday's Internal Search Interface

Workday's internal search interface

Workday is investigating ways to support business intelligence and analytics from within their application. With the data being separated from the screens, manipulating that data is easy. Providing functionality such as drill-down capabilities on totals is one such example. In the past, other systems made users run a new report to see what numbers were behind that total. In Workday's system, the user merely has to click the number and instantly receive a breakdown so he or she can make better judgments faster and easier.

Conclusion

As you can see, RIA is no longer just an abstract term in the software industry. It truly is a new programming paradigm. If corporations have embraced this new way of working, then it's safe to say this is not a fad. Consumers have been enjoying the benefits the RIA technologies for quite some time outside of work. It was only a matter of time before they started to demand that richness in their corporate lives as well.

The amazing thing about this next generation of applications is the desire to change the paradigm. Whether it be through hosting customer applications, creating in-memory systems, or bringing richness to the experience, these companies are on a never-ending quest for constant innovation. "While our UI is one of the most advanced ones in the ERP space, we at Workday still see room for improvement," concluded Bonadio. "We're just getting started."

[架构]说说大型高并发高负载网站的系统架构

mikel阅读(769)

原文链接:(俊麟 Michael’s blog )http://www.toplee.com/blog/71.html
  注:原文链接后的相关评论也很精彩,建议也参考一下原文链接后的评论。
  
    我在CERNET做过拨号接入平台的搭建,而后在Yahoo&3721从事过搜索引擎前端开发,又在MOP处理过大型社区猫扑大 杂烩的架构升级等工作,同时自己接触和开发过不少大中型网站的模块,因此在大型网站应对高负载和并发的解决方案上有一些积累和经验,可以和大家一起探讨一 下。
  
  
    一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下, 这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来 说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的 html静态网站所能比拟的。
  
    大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。
  
    上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。
  
  1、HTML静态化
    其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单 的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问 的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备 频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
  
    除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进 行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。目前很多博客也都实现了静态 化,我使用的这个Blog程序WordPress还没有静态化,所以如果面对高负载访问,www.toplee.com一定不能承受
  
    同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来 实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很 小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
  
    在进行html静态化的时候可以使用一种折中的方法,就是前端使用动态实现,在一定的策略下进行定时静态化和定时判断调用,这个能实现很多灵活性的操作,我开发的台球网站故人居(www.8zone.cn)就是使用了这样的方法,我通过设定一些html静态化的时间间隔来对动态网站内容进行缓存,达到分担大部分的压力到静态页面上,可以应用于中小型网站的架构上。故人居网站的地址:http://www.8zone.cn,顺便提一下,有喜欢台球的朋友多多支持我这个免费网站:)
  
  2、图片服务器分离
    大家知道,对于Web服务器来说,不管是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离, 这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保 证系统不会因为图片问题而崩溃。
  
    在应用服务器和图片服务器上,可以进行不同的配置优化,比如Apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消耗和执行效率。
  
    我的台球网站故人居8zone.cn也使用了图片服务器架构上的分离,目前是仅仅是架构上分离,物理上没有分离,由于没有钱买更多的服务器:),大家可以看到故人居上的图片连接都是类似img.9tmd.com或者img1.9tmd.com的URL。
  
    另外,在处理静态页面或者图片、js等访问方面,可以考虑使用lighttpd代替Apache,它提供了更轻量级和更高效的处理能力。
  
  3、数据库集群和库表散列
    大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
  
    在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
  
    上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库 表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略 对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就 是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单 的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
  
  4、缓存
    缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。
  
    架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的mod_proxy缓存模块,也可以使用外加的Squid进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。
  
    网站程序开发方面的缓存,Linux上提供的Memcached是常用的缓存方案,不少web编程语言都提供memcache访问接口, php、perl、c和java都有,可以在web开发中使用,可以实时或者Cron的把数据、对象等内容进行缓存,策略非常灵活。一些大型社区使用了这 样的架构。
  
    另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块和 eAccelerator加速和Cache模块,还要知名的Apc、XCache(国人开发的,支持!)php缓存模块,Java就更多了,.net不是 很熟悉,相信也肯定有。
  
  5、镜像
    镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如 ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太 深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。
  
  6、负载均衡
    负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。
  
    负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。另外有关初级的负载均衡DNS轮循和较专业的CDN架构就不多说了。
  
  6.1 硬件四层交换
    第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四 层交换功能就象是虚IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器 基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和 UDP端口共同决定。
  
    在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。
  
  6.2 软件四层交换
    大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。
  
    软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满 足多种应用需求,这对于分布式的系统来说必不可少。
  
    一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用, 这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。
  
  总结:
    对于大型网站来说,前面提到的每个方法可能都会被同时使用到,Michael这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢 熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。

[架构]最便宜的高负载网站架构

mikel阅读(864)

  原文链接:http://www.javaeye.com/blog/52178
  说明:可以参看原链接的评论
  ===================================================
  1, LVS做前端四层均衡负载
  基于IP虚拟分发的规则,不同于apache,squid这些7层基于http协议的反向代理软件, LVS在性能上往往能得到更好的保证!
  
  2,squid 做前端反向代理加缓存
  squid 是业内公认的优秀代理服务器,其缓存能力更让许多高负载网站青睐!(比如新浪,网易等)
  使用他, 配合ESI做WEB动态内容及图片缓存,最合适不过了
  
  3,apache 用来处理php或静态html,图片
  apache是业内主流http服务器,稳定性与性能都能得到良好保证!
  
  4,JBOSS 用来处理含复杂的业务逻辑的请求
  JBOSS是red hat旗下的优秀中间件产品,在java开源领域小有名气,并且完全支持j2ee规范的,功能非常强大
  使用他,既能保证业务流程的规范性,又可以节省开支(免费的)
  
  5,mySQL数据库
  使用mySQL数据库,达到百万级别的数据存储,及快速响应,应该是没问题的
  
  6,memcache作为分布式缓存
  缓存应用数据,或通过squid解析esi后,作为数据载体

[教程]Linq to SQL 查询

mikel阅读(700)

原贴
    简单地说,LINQ 是支持以类型安全方式查询数据的一系列语言扩展;它将在代号为“Orcas”的下一个版本 Visual Studio 中发布。待查询数据的形式可以是 XML(LINQ 到 XML)、数据库(启用 LINQ 的 ADO.NET,其中包括 LINQ 到 SQL、LINQ 到 Dataset 和 LINQ 到 Entities)和对象 (LINQ 到 Objects) 等。LINQ 体系结构如图 1 所示。


让我们看一些代码。在即将发布的“Orcas”版 C# 中,LINQ 查询可能如下所示:

var overdrawnQuery = from account in db.Accounts

                     where account.Balance < 0

                     select new { account.Name, account.Address };

当使用 foreach 遍历此查询的结果时,返回的每个元素都将包含一个余额小于 0 的帐户的名称和地址。

从 以上示例中立即可以看出该语法类似于 SQL。几年前,Anders Hejlsberg(C# 的首席设计师)和 Peter Golde 曾考虑扩展 C# 以更好地集成数据查询。Peter 时任 C# 编译器开发主管,当时正在研究扩展 C# 编译器的可能性,特别是支持可验证 SQL 之类特定于域的语言语法的加载项。另一方面,Anders 则在设想更深入、更特定级别的集成。他当时正在构思一组“序列运算符”,能在实现 IEnumerable 的任何集合以及实现 IQueryable 的远程类型查询上运行。最终,序列运算符的构思获得了大多数支持,并且 Anders 于 2004 年初向比尔·盖茨的 Thinkweek 递交了一份关于本构思的文件。反馈对此给予了充分肯定。在设计初期,简单查询的语法如下所示:

sequence<Customer> locals = customers.where(ZipCode == 98112);

在 此例中,Sequence 是 IEnumerable<T> 的别名;“where”一词是编译器能理解的一种特殊运算符。Where 运算符的实现是一种接受 predicate 委托(即 bool Pred<T>(T item) 形式的委托)的普通 C# 静态方法。本构思的目的是让编辑器具备与运算符有关的特殊知识。这样将允许编译器正确调用静态方法并创建代码,将委托与表达式联系起来。

假设上述示例是 C# 的理想查询语法。在没有任何语言扩展的情况下,该查询在 C# 2.0 中又会是什么样子?

IEnumerable<Customer> locals = EnumerableExtensions.Where(customers,

                                                    delegate(Customer c)

        {

            return c.ZipCode == 98112;

        });

这 个代码惊人地冗长,而且更糟糕的是,需要非常仔细地研究才能找到相关的筛选器 (ZipCode == 98112)。这只是一个简单的例子;试想一下,如果使用数个筛选器、投影等,要读懂代码该有多难。冗长的根源在于匿名方法所要求的语法。在理想的查询 中,除了要计算的表达式,表达式不会提出任何要求。随后,编译器将尝试推断上下文;例如,ZipCode 实际上引用了 Customer 上定义的 ZipCode。如何解决这一问题?将特定运算符的知识硬编码到语言中并不能令语言设计团队满意,因此他们开始为匿名方法寻求替代语法。他们要求该语法应 极其简练,但又不必比匿名方法当前所需的编译器要求更多的知识。最终,他们发明了 lambda 表达式。


Lambda
表达式

Lambda 表 达式是一种语言功能,在许多方面类似于匿名方法。事实上,如果 lambda 表达式首先被引入语言,那么就不会有对匿名方法的需要了。这里的基本概念是可以将代码视为数据。在 C# 1.0 中,通常可以将字符串、整数、引用类型等传递给方法,以便方法对那些值进行操作。匿名方法和 lambda 表达式扩展了值的范围,以包含代码块。此概念常见于函数式编程中。

我们再借用以上示例,并用 lambda 表达式替换匿名方法:

IEnumerable<Customer> locals =

    EnumerableExtensions.Where(customers, c => c.ZipCode == 91822);

有 几个需要注意的地方。对于初学者而言, lambda 表达式简明扼要的原因有很多。首先,没有使用委托关键字来引入构造。取而代之的是一个新的运算符 =>,通知编译器这不是正则表达式。其次,Customer 类型是从使用中推断出来的。在此例中,Where 方法的签名如下所示:

public static IEnumerable<T> Where<T>(

    IEnumerable<T> items, Func<T, bool> predicate)

编 译器能够推断“c”是指客户,因为 Where 方法的第一个参数是 IEnumerable<Customer>,因此 T 事实上必须是 Customer。利用这种知识,编译器还可验证 Customer 具有一个 ZipCode 成员。最后,没有指定的返回关键字。在语法形式中,返回成员被省略,但这只是为了语法便利。表达式的结果仍将视为返回值。

与匿名方法一样,Lambda 表达式也支持变量捕获。例如,对于在 lambda 表达式主体内包含 lambda 表达式的方法,可以引用其参数或局部变量:

public IEnumerable<Customer> LocalCusts(

    IEnumerable<Customer> customers, int zipCode)

{

    return EnumerableExtensions.Where(customers,

        c => c.ZipCode == zipCode);

}

最后,Lambda 表达式支持更冗长的语法,允许您显式指定类型,以及执行多条语句。例如:

return EnumerableExtensions.Where(customers,

    (Customer c) => { int zip = zipCode; return c.ZipCode == zip; });

好消息是,我们向原始文章中提议的理想语法迈进了一大步,并且我们能够利用一个通常能在查询运算符以外发挥作用的语言功能来实现这一目标。让我们再次看一下我们目前所处的阶段:

IEnumerable<Customer> locals =

    EnumerableExtensions.Where(customers, c => c.ZipCode == 91822);

这里存在一个明显的问题。客户目前必须了解此 EnumerableExtensions 类,而不是考虑可在 Customer 上执行的操作。另外,在多个运算符的情况下,使用者必须逆转其思维以编写正确的语法。例如:

IEnumerable<string> locals =

    EnumerableExtensions.Select(

        EnumerableExtensions.Where(customers, c => c.ZipCode == 91822),

        c => c.Name);

请注意,Select 属于外部方法,尽管它是在 Where 方法结果的基础上运行的。理想的语法应该更类似以下代码:

sequence<Customer> locals =

    customers.where(ZipCode == 98112).select(Name);

因此,是否可利用另一种语言功能来进一步接近实现理想语法呢?


扩展方法

结 果证明,更好的语法将以被称为扩展方法的语言功能形式出现。扩展方法基本上属于可通过实例语法调用的静态方法。上述查询问题的根源是我们试图向 IEnumerable<T> 添加方法。但如果我们要添加运算符,如 Where、Select 等,则所有现有和未来的实现器都必须实现那些方法。尽管那些实现绝大多数都是相同的。在 C# 中共享“接口实现”的唯一方法是使用静态方法,这是我们处理以前使用的 EnumerableExtensions 类的一个成功方法。

假设我们转而将 Where 方法编写为扩展方法。那么,查询可重新编写为:

IEnumerable<Customer> locals =

    customers.Where(c => c.ZipCode == 91822);

对于此简单查询,该语法近乎完美。但将 Where 方法编写为扩展方法的真正含义是什么呢?其实非常简单。基本上,因为静态方法的签名发生更改,因此“this”修饰符就被添加到第一个参数:

public static IEnumerable<T> Where<T>(

    this IEnumerable<T> items, Func<T, bool> predicate)

此 外,必须在静态类中声明该方法。静态类是一种只能包含静态成员,并在类声明中用静态修饰符表示的类。这就它的全部含义。此声明指示编译器允许在任何实现 IEnumerable<T> 的类型上用与实例方法相同的语法调用 Where。但是,必须能够从当前作用域访问 Where 方法。当包含类型处于作用域内时,方法也在作用域内。因此,可以通过 Using 指令将扩展方法引入作用域。(有关详细信息,请参见侧栏上的“扩展方法”。)

扩展方法

显然,扩展 方法有助于简化我们的查询示例,但除此之外,这些方法是不是一种广泛有用的语言功能呢?事实证明扩展方法有多种用途。其中一个最常见的用途可能是提供共享接口实现。例如,假设您有以下接口:

interface IDog

{

    // Barks for 2 seconds

    void Bark();

    void Bark(int seconds);

}

此接口要求每个实现器都应编写适用于两种重载的实现。有了“Orcas”版 C#,接口变得很简单:

interface IDog

{

    void Bark(int seconds);

}

扩展方法可添加到另一个类:

static class DogExtensions

{

    // Barks for 2 seconds

    public static void Bark(this IDog dog)

    {

        dog.Bark(2);

    }

}

接口实现器现在只需实现单一方法,但接口客户端却可以自由调用任一重载。

我们现在拥有了用于编写筛选子句的非常接近理想的语法,但“Orcas”版 C# 仅限于此吗?并不全然。让我们对示例稍作扩展,相对于整个客户对象,我们只投影出客户名称。如我前面所述,理想的语法应采用如下形式:

sequence<string> locals =

    customers.where(ZipCode == 98112).select(Name);

仅用我们讨论过的语言扩展,即 lambda 表达式和扩展方法,此代码可重新编写为如下所示:

IEnumerable<string> locals =

    customers.Where(c => c.ZipCode == 91822).Select(c => c.Name);

请注意,此查询的返回类型不同,它是 IEnumerable<string> 而不是 IEnumerable<Customer>。这是因为我们仅从 select 语句中返回客户名称。

当投影只是单一字段时,该方法确实很有效。但是,假设我们不仅要返回客户的名称,还要返回客户的地址。理想的语法则应如下所示:

locals = customers.where(ZipCode == 98112).select(Name, Address);


匿名类型

如果我们想继续使用我们现有的语法来返回名称和地址,我们很快便会面临问题,即不存在仅包含 Name 和 Address 的类型。虽然我们仍然可以编写此查询,但是必须引入该类型:

class CustomerTuple

{

    public string Name;

    public string Address;

    public CustomerTuple(string name, string address)

    {

        this.Name = name;

        this.Address = address;

    }

}

然后我们才能使用该类型,即此处的 CustomerTuple,以生成我们查询的结果。

IEnumerable<CustomerTuple> locals =

    customers.Where(c => c.ZipCode == 91822)

                 .Select(c => new CustomerTuple(c.Name, c.Address));

那 确实像许多用于投影出字段子集的样板代码。而且还往往不清楚如何命名此种类型。CustomerTuple 确实是个好名称吗?如果投影出 Name 和 Age 又该如何命名?那也可以叫做 CustomerTuple。因此,问题在于我们拥有样板代码,而且似乎无法为我们创建的类型找到任何恰当的名称。此外,还可能需要许多不同的类型,如何 管理这些类型很快便可能成为一个棘手的问题。

这正是匿名类型要解决的问题。此功能主要允许在无需指定名称的情况下创建结构化类型。如果我们使用匿名类型重新编写上述查询,其代码如下所示:

locals = customers.Where(c => c.ZipCode == 91822)

                       .Select(c => new { c.Name, c.Address });

此代码会隐式创建一个具有 Name 和 Address 字段的类型:

class

{

    public string Name;

    public string Address;

}

此类型不能通过名称引用,因为它没有名称。创建匿名类型时,可显式声明字段的名称。例如,如果正在创建的字段派生于一条复杂的表达式,或纯粹不需要名称,就可以更改名称:

locals = customers.Where(c => c.ZipCode == 91822)

    .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                       HomeAddress = c.Address });

在此情形下,生成的类型具有名为 FullName 和 HomeAddress 的字段。

这样我们又向理想世界前进了一步,但仍存在一个问题。您将发现,我在任何使用匿名类型的地方都策略性地省略了局部变量的类型。显然我们不能声明匿名类型的名称,那我们如何使用它们?


隐式类型化部变量

还有另一种语言功能被称为隐式类型化局部变量(或简称为 var),它负责指示编译器推断局部变量的类型。例如:

var integer = 1;

在此例中,整数具有 int 类型。请务必明白,这仍然是强类型。在动态语言中,整数的类型可在以后更改。为说明这一点,以下代码不会成功编译:

var integer = 1;

integer = “hello”;

C# 编译器将报告第二行的错误,表明无法将字符串隐式转换为 int。

在上述查询示例中,我们现在可以编写完整的赋值,如下所示:

var locals =

   customers

       .Where(c => c.ZipCode == 91822)

       .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                          HomeAddress = c.Address });

局部变量的类型最终成为 IEnumerable<?>,其中“?”是无法编写的类型的名称(因为它是匿名的)。

隐式类型化局部变量只是:方法内部的局部变量。它们无法超出方法、属性、索引器或其他块的边界,因为该类型无法显式声明,而且“var”对于字段或参数类型而言是非法的。

事实证明,隐式类型化局部变量在查询的环境之外非常便利。例如,它有助于简化复杂的通用实例化:

var customerListLookup = new Dictionary<string, List<Customer>>();

现在我们的查询取得了良好进展;我们已经接近理想的语法,而且我们是用通用语言功能来达成的。

有趣的是,我们发现,随着越来越多的人使用过此语法,经常会出现允许投影超越方法边界的需求。如我们以前所看到的,这是可能的,只要从 Select 内部调用对象的构造函数来构建对象即可。但是,如果没有用来准确接受您需要设置的值的构造函数,会发生什么呢?


对象初始值

为解决这一问题,即将发布的“Orcas”版本提供了一种被称为对象初始值的 C# 语言功能。对象初始值主要允许在单一表达式中为多个属性或字段赋值。例如,创建对象的常见模式是:

Customer customer = new Customer();

customer.Name = “Roger”;

customer.Address = “1 Wilco Way”;

此时,Customer 没有可以接受名称和地址的构造函数;但是存在两个属性,即 Name 和 Address,当创建实例后即可设置它们。对象初始值允许使用以下语法创建相同的结果:

Customer customer = new Customer()

    { Name = “Roger”, Address = “1 Wilco Way” };

在我们前面的 CustomerTuple 示例中,我们通过调用其构造函数创建了 CustomerTuple 类。我们也可以通过对象初始值获得同样的结果:

var locals =

    customers

        .Where(c => c.ZipCode == 91822)

        .Select(c =>

             new CustomerTuple { Name = c.Name, Address = c.Address });

请注意,对象初始值允许省略构造函数的括号。此外,字段和可设置的属性均可在对象初始值的主体内部进行赋值。

我们现在已经拥有在 C# 中创建查询的简洁语法。尽管如此,我们还有一种可扩展途径,可通过扩展方法以及一组本身非常有用的语言功能来添加新的运算符(Distinct、OrderBy、Sum 等)。

语 言设计团队现在有了数种可赖以获得反馈的原型。因此,我们与许多富于 C# 和 SQL 经验的参与者组织了一项可用性研究。几乎所有反馈都是肯定的,但明显疏忽了某些东西。具体而言,开发人员难以应用他们的 SQL 知识,因为我们认为理想的语法与他们擅长领域的专门技术并不很符合。


查询表达式

于是,语言设计团队设计了一种与 SQL 更为相近的语法,称为查询表达式。例如,针对我们的示例的查询表达式可如下所示:

var locals = from c in customers

             where c.ZipCode == 91822

             select new { FullName = c.FirstName + “ “ +

                          c.LastName, HomeAddress = c.Address };

查询表达式是基于上述语言功能构建而成。它们在语法上,完全转换为我们已经看到的基础语法。例如,上述查询可直接转换为:

var locals =

   customers

       .Where(c => c.ZipCode == 91822)

       .Select(c => new { FullName = c.FirstName + “ “ + c.LastName,

                          HomeAddress = c.Address });

查 询表达式支持许多不同的“子句”,如 from、where、select、orderby、group by、let 和 join。这些子句先转换为对等的运算符调用,后者进而通过扩展方法实现。如果查询语法不支持必要运算符的子句,则查询子句和实现运算符的扩展方法之间的 紧密关系很便于将两者结合。例如:

var locals = (from c in customers

              where c.ZipCode == 91822

              select new { FullName = c.FirstName + “ “ +

                          c.LastName, HomeAddress = c.Address})

             .Count();

在本例中,查询现在返回在 91822 ZIP Code 区居住的客户人数。

通 过该种方法,我们已经设法在结束时达到了开始时的目标(我对这一点始终觉得非常满意)。下一版本的 C# 的语法历经数年时间的发展,尝试了许多新的语言功能,才最终到达近乎于 2004 年冬提议的原始语法的境界。查询表达式的加入以 C# 即将发布的版本的其他语言功能为基础,并促使许多查询情况更便于具有 SQL 背景的开发人员阅读和理解。

[文档]SQL Server 2000 系统表和 SQL Server 2005 系统视图之间的映射

mikel阅读(847)

本主题说明了 SQL Server 2000 系统表和 SQL Server 2005 系统视图之间的映射。

下表将 SQL Server 2000 中 master 数据库内的系统表映射到它们在 SQL Server 2005 中对应的一个或多个系统视图。

系统表 系统视图 视图类型

sysaltfiles

sys.master_files

目录视图

syscacheobjects

sys.dm_exec_cached_plans

动态管理视图

syscharsets

sys.syscharsets

兼容性视图

sysconfigures

sys.configurations

目录视图

syscurconfigs

sys.configurations

目录视图

sysdatabases

sys.databases

目录视图

sysdevices

sys.backup_devices

目录视图

syslanguages

sys.syslanguages

兼容性视图

syslockinfo

sys.dm_tran_locks

动态管理视图

syslocks

sys.dm_tran_locks

动态管理视图

syslogins

sys.server_principals

目录视图

sysmessages

sys.messages

目录视图

sysoledbusers

sys.linked_logins

目录视图

sysopentapes

sys.dm_io_backup_tapes

动态管理视图

sysperfinfo

sys.dm_os_performance_counters

动态管理视图

sysprocesses

sys.dm_exec_connections

sys.dm_exec_sessions

sys.dm_exec_requests

动态管理视图

sysremotelogins

sys.remote_logins

目录视图

sysservers

sys.servers

目录视图

下表将 SQL Server 2000 中每个数据库内的系统表映射到它们在 SQL Server 2005 中对应的一个或多个系统视图。

系统表 系统视图 视图类型

syscolumns

sys.columns

目录视图

syscomments

sys.sql_modules

目录视图

sysconstraints

sys.check_constraints

sys.default_constraints

sys.key_constraints

sys.foreign_keys

目录视图

sysdepends

sys.sql_dependencies

目录视图

sysfilegroups

sys.filegroups

目录视图

sysfiles

sys.database_files

目录视图

sysforeignkeys

sys.foreign_keys

目录视图

sysindexes

sys.indexes

目录视图

sysindexkeys

sys.index_columns

目录视图

sysmembers

sys.database_role_members

目录视图

sysobjects

sys.objects

目录视图

syspermissions

sys.database_permissions

sys.server_permissions

目录视图

sysprotects

sys.database_permissions

sys.server_permissions

目录视图

sysreferences

sys.foreign_keys

目录视图

systypes

sys.types

目录视图

sysusers

sys.database_principals

目录视图

sysfulltextcatalogs

sys.fulltext_catalogs

目录视图

[代码]SQLServer2005读取表信息

mikel阅读(851)

declare @schemaName varchar(100)
declare @tblName varchar(100)
declare @colName varchar(100)
declare @objectID int
set @schemaName = 'College'
set @tblName = 'Student'
set @colName = 'iStatusID'
set @objectID = OBJECT_ID(@schemaName + '.' + @tblName)
— 1. How to check the Column is nullable?
Select COLUMNPROPERTY(@objectID,@colName,'AllowsNull') AS 'Allows Null?';
— 2. How to check the Column is an identity?
Select COLUMNPROPERTY(@objectID,@colName,'IsIdentity') AS 'Identity?';
— 3. How to check the Column is an FullTextEnabled?
Select COLUMNPROPERTY(@objectID,@colName,'IsFulltextIndexed') AS 'FullTextEnabled?';
— 4. How to check the Column's datatype?
select b.name as 'Datatype', a.max_length, a.precision, a.scale
from sys.columns a
join sys.types b on a.system_type_id = b.system_type_id and a.user_type_id = b.user_type_id
where OBJECT_NAME(a.object_id) = @tblName and a.name = @colName
— 5. How to identify that the default constraints have been created for the Column?
select a.name as 'Default Constraint Name'
from sys.default_constraints a
join sys.all_columns b on a.parent_object_id = b.object_id and a.parent_column_id = b.column_id
where object_name(parent_object_id) = @tblName and b.name = @colName
— 6. How to identify that the foreignkey constraints for the table?
select name as 'ForeignKeyConstraint Name' from sys.objects
where type = 'F' and parent_object_id = @objectID
— 7. Select all Constraints associated with this table and Column.
Select Constraint_Name from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
Where Table_Name = @tblName and Column_Name = @colName
— 8. Find all the Objects from sys.objects table by specifying the “type”.
select name from sys.objects Where parent_object_id = @objectID and type = 'D'