<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_hello</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/38945/rss</id><updated>2011-08-07T13:55:31Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/38945/rss"/><entry><id>http://www.cnblogs.com/h-hello/articles/2130303.html</id><title type="text">【转】jQuery最佳实践</title><summary type="text">上周，我整理了《jQuery设计思想》。那篇文章是一篇入门教程，从设计思想的角度，讲解&amp;quot;怎么使用jQuery&amp;quot;。今天的文章则是更进一步，讲解&amp;quot;如何用好jQuery&amp;quot;。我主要参考了Addy Osmani的PPT《提高jQuery性能的诀窍》（jQuery Proven Performance Tips And Tricks）。他是jQuery开发团队的成员，具有一定的权威性，提出的结论都有测试数据支持，非常有价值。==============================================jQuery最佳实践阮一峰 整理1. 使用最新版本的</summary><published>2011-08-07T13:56:00Z</published><updated>2011-08-07T13:56:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/2130303.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/2130303.html"/><content type="html">&lt;p&gt;上周，我整理了&lt;a href="http://www.ruanyifeng.com/blog/2011/07/jquery_fundamentals.html"&gt;《jQuery设计思想》&lt;/a&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;那篇文章是一篇入门教程，从设计思想的角度，讲解&lt;strong&gt;"&lt;/strong&gt;&lt;strong&gt;怎么使用jQuery"&lt;/strong&gt;。今天的文章则是更进一步，讲解&lt;strong&gt;"&lt;/strong&gt;&lt;strong&gt;如何用好jQuery"&lt;/strong&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;我主要参考了Addy Osmani的PPT&lt;a href="http://addyosmani.com/jqprovenperformance/"&gt;《提高jQuery性能的诀窍》&lt;/a&gt;（jQuery Proven Performance Tips And Tricks）。他是jQuery开发团队的成员，具有一定的权威性，提出的结论都有测试数据支持，非常有价值。&lt;/p&gt;&#xD;
&lt;p&gt;==============================================&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;jQuery&lt;/strong&gt;&lt;strong&gt;最佳实践&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;阮一峰 整理&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://pic003.cnblogs.com/2011/34358/201108/20110804161730149.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px;" title="clip_image001" border="0" alt="clip_image001" src="http://pic003.cnblogs.com/2011/34358/201108/20110804161730292.jpg" width="609" height="463" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1. &lt;/strong&gt;&lt;strong&gt;使用最新版本的jQuery&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;jQuery的版本更新很快，你应该总是使用最新的版本。因为新版本会改进性能，还有很多新功能。&lt;/p&gt;&#xD;
&lt;p&gt;下面就来看看，不同版本的jQuery性能差异有多大。这里是三条最常见的jQuery选择语句：&lt;/p&gt;&#xD;
&lt;p&gt;$('.elem')&lt;/p&gt;&#xD;
&lt;p&gt;$('.elem', context)&lt;/p&gt;&#xD;
&lt;p&gt;context.find('.elem')&lt;/p&gt;&#xD;
&lt;p&gt;我们用1.4.2、1.4.4、1.6.2三个版本的jQuery&lt;a href="http://jsperf.com/jquery-1-4-2-vs-1-6-2-comparisons"&gt;测试&lt;/a&gt;，看看浏览器在1秒内能够执行多少次。结果如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://pic003.cnblogs.com/2011/34358/201108/20110804161730543.gif"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px;" title="clip_image002" border="0" alt="clip_image002" src="http://pic003.cnblogs.com/2011/34358/201108/20110804161730599.gif" width="620" height="342" /&gt;&lt;/a&gt;可以看到，1.6.2版本的运行次数，远远超过两个老版本。尤其是第一条语句，性能有数倍的提高。&lt;/p&gt;&#xD;
&lt;p&gt;其他语句的测试，比如&lt;a href="http://jsperf.com/attr-vs-attrhooks"&gt;.attr("value")&lt;/a&gt;和&lt;a href="http://jsperf.com/valhooks-vs-val/2"&gt;.val()&lt;/a&gt;，也是新版本的jQuery表现好于老版本。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2. &lt;/strong&gt;&lt;strong&gt;用对选择器&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在jQuery中，你可以用多种选择器，选择同一个网页元素。每种选择器的性能是不一样的，你应该了解它们的性能差异。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;（1）最快的选择器：id选择器和元素标签选择器&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;举例来说，下面的语句性能最佳：&lt;/p&gt;&#xD;
&lt;p&gt;$('#id')&lt;/p&gt;&#xD;
&lt;p&gt;$('form')&lt;/p&gt;&#xD;
&lt;p&gt;$('input')&lt;/p&gt;&#xD;
&lt;p&gt;遇到这些选择器的时候，jQuery内部会自动调用浏览器的原生方法（比如getElementById()），所以它们的执行速度快。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;（2）较慢的选择器：class选择器&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;$('.className')的性能，取决于不同的浏览器。&lt;/p&gt;&#xD;
&lt;p&gt;Firefox、Safari、Chrome、Opera浏览器，都有原生方法getElementByClassName()，所以速度并不慢。但是，IE5-IE8都没有部署这个方法，所以这个选择器在IE中会相当慢。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;（3）最慢的选择器：伪类选择器和属性选择器&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;先来看例子。找出网页中所有的隐藏元素，就要用到伪类选择器：&lt;/p&gt;&#xD;
&lt;p&gt;$(':hidden')&lt;/p&gt;&#xD;
&lt;p&gt;属性选择器的例子则是：&lt;/p&gt;&#xD;
&lt;p&gt;$('[attribute=value]')&lt;/p&gt;&#xD;
&lt;p&gt;这两种语句是最慢的，因为浏览器没有针对它们的原生方法。但是，一些浏览器的新版本，增加了querySelector()和querySelectorAll()方法，因此会使这类选择器的性能有大幅提高。&lt;/p&gt;&#xD;
&lt;p&gt;最后是不同选择器的&lt;a href="http://jsperf.com/dh-jquery-1-4-vs-1-6/6"&gt;性能比较图&lt;/a&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://pic003.cnblogs.com/2011/34358/201108/20110804161731170.gif"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto; border-width: 0px;" title="clip_image003" border="0" alt="clip_image003" src="http://pic003.cnblogs.com/2011/34358/201108/2011080416173162.gif" width="626" height="356" /&gt;&lt;/a&gt;可以看到，ID选择器遥遥领先，然后是标签选择器，第三是Class选择器，其他选择器都非常慢。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. &lt;/strong&gt;&lt;strong&gt;理解子元素和父元素的关系&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;下面六个选择器，都是从父元素中选择子元素。你知道哪个速度最快，哪个速度最慢吗？&lt;/p&gt;&#xD;
&lt;p&gt;$('.child', $parent)&lt;/p&gt;&#xD;
&lt;p&gt;$parent.find('.child')&lt;/p&gt;&#xD;
&lt;p&gt;$parent.children('.child')&lt;/p&gt;&#xD;
&lt;p&gt;$('#parent &amp;gt; .child')&lt;/p&gt;&#xD;
&lt;p&gt;$('#parent .child')&lt;/p&gt;&#xD;
&lt;p&gt;$('.child', $('#parent'))&lt;/p&gt;&#xD;
&lt;p&gt;我们一句句来看。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(1) $('.child', $parent)&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这条语句的意思是，给定一个DOM对象，然后从中选择一个子元素。jQuery会自动把这条语句转成$.parent.find('child')，这会导致一定的性能损失。它比最快的形式慢了5%-10%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(2) $parent.find('.child')&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这条是最快的语句。.find()方法会调用浏览器的原生方法（getElementById，getElementByName，getElementByTagName等等），所以速度较快。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(3) $parent.children('.child')&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这条语句在jQuery内部，会使用$.sibling()和javascript的nextSibling()方法，一个个遍历节点。它比最快的形式大约慢50%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(4) $('#parent &amp;gt; .child')&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;jQuery内部使用Sizzle引擎，处理各种选择器。Sizzle引擎的选择顺序是从右到左，所以这条语句是先选.child，然后再一个个过滤出父元素#parent，这导致它比最快的形式大约慢70%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(5) $('#parent .child')&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这条语句与上一条是同样的情况。但是，上一条只选择直接的子元素，这一条可以于选择多级子元素，所以它的速度更慢，大概比最快的形式慢了77%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(6) $('.child', $('#parent'))&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;jQuery内部会将这条语句转成$('#parent').find('.child')，比最快的形式慢了23%。&lt;/p&gt;&#xD;
&lt;p&gt;所以，最佳选择是$parent.find('.child')。而且，由于$parent往往在前面的操作已经生成，jQuery会进行缓存，所以进一步加快了执行速度。&lt;/p&gt;&#xD;
&lt;p&gt;具体的例子和比较结果，请看&lt;a href="http://jsperf.com/jquery-selectors-context/2"&gt;这里&lt;/a&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. &lt;/strong&gt;&lt;strong&gt;不要过度使用jQuery&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;jQuery速度再快，也无法与原生的javascript方法相比。所以有原生方法可以使用的场合，尽量避免使用jQuery。&lt;/p&gt;&#xD;
&lt;p&gt;请看下面的例子，为a元素绑定一个处理点击事件的函数：&lt;/p&gt;&#xD;
&lt;p&gt;$('a').click(function(){&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;alert($(this).attr('id'));&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;});&lt;/p&gt;&#xD;
&lt;p&gt;这段代码的意思是，点击a元素后，弹出该元素的id属性。为了获取这个属性，必须连续两次调用jQuery，第一次是$(this)，第二次是attr('id')。&lt;/p&gt;&#xD;
&lt;p&gt;事实上，这种处理完全不必要。更正确的写法是，直接采用javascript原生方法，调用this.id：&lt;/p&gt;&#xD;
&lt;p&gt;$('a').click(function(){&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;alert(this.id);&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;});&lt;/p&gt;&#xD;
&lt;p&gt;根据&lt;a href="http://jsperf.com/el-attr-id-vs-el-id/2"&gt;测试&lt;/a&gt;，this.id的速度比$(this).attr('id')快了20多倍。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5. &lt;/strong&gt;&lt;strong&gt;做好缓存&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;选中某一个网页元素，是开销很大的步骤。所以，使用选择器的次数应该越少越好，并且尽可能缓存选中的结果，便于以后反复使用。&lt;/p&gt;&#xD;
&lt;p&gt;比如，下面这样的写法就是糟糕的写法：&lt;/p&gt;&#xD;
&lt;p&gt;jQuery('#top').find('p.classA');&lt;/p&gt;&#xD;
&lt;p&gt;jQuery('#top').find('p.classB');&lt;/p&gt;&#xD;
&lt;p&gt;更好的写法是：&lt;/p&gt;&#xD;
&lt;p&gt;var cached = jQuery('#top');&lt;/p&gt;&#xD;
&lt;p&gt;cached.find('p.classA');&lt;/p&gt;&#xD;
&lt;p&gt;cached.find('p.classB');&lt;/p&gt;&#xD;
&lt;p&gt;根据&lt;a href="http://jsperf.com/ns-jq-cached"&gt;测试&lt;/a&gt;，缓存比不缓存，快了2-3倍。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;6. &lt;/strong&gt;&lt;strong&gt;使用链式写法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;jQuery的一大特点，就是允许使用链式写法。&lt;/p&gt;&#xD;
&lt;p&gt;$('div').find('h3').eq(2).html('Hello');&lt;/p&gt;&#xD;
&lt;p&gt;采用链式写法时，jQuery自动缓存每一步的结果，因此比非链式写法要快。根据&lt;a href="http://jsperf.com/jquery-chaining"&gt;测试&lt;/a&gt;，链式写法比（不使用缓存的）非链式写法，大约快了25%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;7. &lt;/strong&gt;&lt;strong&gt;事件的委托处理（Event Delegation）&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;javascript的事件模型，采用"冒泡"模式，也就是说，子元素的事件会逐级向上"冒泡"，成为父元素的事件。&lt;/p&gt;&#xD;
&lt;p&gt;利用这一点，可以大大简化事件的绑定。比如，有一个表格（table元素），里面有100个格子（td元素），现在要求在每个格子上面绑定一个点击事件（click），请问是否需要将下面的命令执行100次？&lt;/p&gt;&#xD;
&lt;p&gt;$("td").bind("click", function(){&lt;/p&gt;&#xD;
&lt;p&gt;$(this).toggleClass("click");&lt;/p&gt;&#xD;
&lt;p&gt;});&lt;/p&gt;&#xD;
&lt;p&gt;回答是不需要，我们只要把这个事件绑定在table元素上面就可以了，因为td元素发生点击事件之后，这个事件会"冒泡"到父元素table上面，从而被监听到。&lt;/p&gt;&#xD;
&lt;p&gt;因此，这个事件只需要在父元素绑定1次即可，而不需要在子元素上绑定100次，从而大大提高性能。这就叫事件的"委托处理"，也就是子元素"委托"父元素处理这个事件。&lt;/p&gt;&#xD;
&lt;p&gt;具体的写法有两种。第一种是采用.delegate()方法：&lt;/p&gt;&#xD;
&lt;p&gt;$("table").delegate("td", "click", function(){&lt;/p&gt;&#xD;
&lt;p&gt;$(this).toggleClass("click");&lt;/p&gt;&#xD;
&lt;p&gt;});&lt;/p&gt;&#xD;
&lt;p&gt;第二种是采用.live()方法：&lt;/p&gt;&#xD;
&lt;p&gt;$("table").each(function(){&lt;/p&gt;&#xD;
&lt;p&gt;$("td", this).live("click", function(){&lt;/p&gt;&#xD;
&lt;p&gt;$(this).toggleClass("click"); &lt;br /&gt;}); &lt;br /&gt;});&lt;/p&gt;&#xD;
&lt;p&gt;这两种写法基本等价。唯一的区别在于，.delegate()是当事件冒泡到指定的父元素时触发，.live()则是当事件冒泡到文档的根元素后触发，因此.delegate()比.live()稍快一点。此外，这两种方法相比传统的.bind()方法还有一个好处，那就是对动态插入的元素也有效，.bind()只对已经存在的DOM元素有效，对动态插入的元素无效。&lt;/p&gt;&#xD;
&lt;p&gt;根据&lt;a href="http://jsperf.com/bind-vs-click/12"&gt;测试&lt;/a&gt;，委托处理比不委托处理，快了几十倍。在委托处理的&lt;a href="http://jsperf.com/jquery-delegate-vs-live-table-test/2"&gt;情况&lt;/a&gt;下，.delegate()又比.live()大约快26%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;8. &lt;/strong&gt;&lt;strong&gt;少改动DOM结构&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;（1）改动DOM结构开销很大，因此不要频繁使用.append()、.insertBefore()和.insetAfter()这样的方法。&lt;/p&gt;&#xD;
&lt;p&gt;如果要插入多个元素，就先把它们合并，然后再一次性插入。根据&lt;a href="http://jsperf.com/string-concat-single-append-vs-multiple-append"&gt;测试&lt;/a&gt;，合并插入比不合并插入，快了将近10倍。&lt;/p&gt;&#xD;
&lt;p&gt;（2）如果你要对一个DOM元素进行大量处理，应该先用.detach()方法，把这个元素从DOM中取出来，处理完毕以后，再重新插回文档。根据&lt;a href="http://jsperf.com/to-detach-or-not-to-detach"&gt;测试&lt;/a&gt;，使用.detach()方法比不使用时，快了60%。&lt;/p&gt;&#xD;
&lt;p&gt;（3）如果你要在DOM元素上储存数据，不要写成下面这样：&lt;/p&gt;&#xD;
&lt;p&gt;var elem = $('#elem');&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;elem.data(key,value);&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;而要写成&lt;/p&gt;&#xD;
&lt;p&gt;var elem = $('#elem');&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;$.data(elem,key,value);&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;根据&lt;a href="http://jsperf.com/jquery-data-vs-jqueryselection-data/11"&gt;测试&lt;/a&gt;， 后一种写法要比前一种写法，快了将近10倍。因为elem.data()方法是定义在jQuery函数的prototype对象上面的， 而$.data()方法是定义jQuery函数上面的，调用的时候不从复杂的jQuery对象上调用，所以速度快得多。（此处可以参阅下面第10点。）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;9. &lt;/strong&gt;&lt;strong&gt;正确处理循环&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;循环总是一种比较耗时的操作，如果可以使用复杂的选择器直接选中元素，就不要使用循环，去一个个辨认元素。&lt;/p&gt;&#xD;
&lt;p&gt;javascript原生循环方法for和while，要比jQuery的.each()方法&lt;a href="http://jsperf.com/jquery-each-vs-for-loop/24"&gt;快&lt;/a&gt;，应该优先使用原生方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;10. &lt;/strong&gt;&lt;strong&gt;尽量少生成jQuery对象&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;每当你使用一次选择器（比如$('#id')），就会生成一个jQuery对象。jQuery对象是一个很庞大的对象，带有很多属性和方法，会占用不少资源。所以，尽量少生成jQuery对象。&lt;/p&gt;&#xD;
&lt;p&gt;举例来说，许多jQuery方法都有两个版本，一个是供&lt;strong&gt;jQuery&lt;/strong&gt;&lt;strong&gt;对象&lt;/strong&gt;使用的版本，另一个是供&lt;strong&gt;jQuery&lt;/strong&gt;&lt;strong&gt;函数&lt;/strong&gt;使用的版本。下面两个例子，都是取出一个元素的文本，使用的都是text()方法。你既可以使用针对jQuery对象的版本：&lt;/p&gt;&#xD;
&lt;p&gt;var $text = $("#text");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;var $ts = $text.text();&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;也可以使用针对jQuery函数的版本：&lt;/p&gt;&#xD;
&lt;p&gt;var $text = $("#text");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;var $ts = $.text($text);&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;由于后一种针对jQuery函数的版本不通过jQuery对象操作，所以相对开销较小，速度&lt;a href="http://jsperf.com/jquery-text-vs-html/5"&gt;比较快&lt;/a&gt;。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/2130303.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/2130303.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/2130299.html</id><title type="text">【转】jQuery设计思想</title><summary type="text">作者： 阮一峰日期： 2011年7月26日jQuery是目前使用最广泛的javascript函数库。据统计，全世界排名前100万的网站，有46%使用jQuery，远远超过其他库。微软公司甚至把jQuery作为他们的官方库。对于网页开发者来说，学会jQuery是必要的。因为它让你了解业界最通用的技术，为将来学习更高级的库打下基础，并且确实可以很轻松地做出许多复杂的效果。虽然jQuery上手简单，比其他库容易学会，但是要全面掌握，却不轻松。因为它涉及到网页开发的方方面面，提供的各种方法和内部变化有上千种之多。初学者常常感到，入门很方便，提高很困难。目前，互联网上最好的jQuery入门教材，是Reb</summary><published>2011-08-07T13:54:00Z</published><updated>2011-08-07T13:54:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/2130299.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/2130299.html"/><content type="html">作者： 阮一峰&#xD;
&#xD;
日期： 2011年7月26日&#xD;
&#xD;
jQuery是目前使用最广泛的javascript函数库。&#xD;
&#xD;
据统计，全世界排名前100万的网站，有46%使用jQuery，远远超过其他库。微软公司甚至把jQuery作为他们的官方库。&#xD;
&#xD;
&#xD;
&#xD;
对于网页开发者来说，学会jQuery是必要的。因为它让你了解业界最通用的技术，为将来学习更高级的库打下基础，并且确实可以很轻松地做出许多复杂的效果。&#xD;
&#xD;
虽然jQuery上手简单，比其他库容易学会，但是要全面掌握，却不轻松。因为它涉及到网页开发的方方面面，提供的各种方法和内部变化有上千种之多。初学者常常感到，入门很方便，提高很困难。&#xD;
&#xD;
目前，互联网上最好的jQuery入门教材，是Rebecca Murphey写的《jQuery基础》（jQuery Fundamentals）。在Google里搜索"jQuery 培训"，此书排在第一位。jQuery官方团队已经同意，把此书作为官方教程的基础。&#xD;
&#xD;
&#xD;
&#xD;
这本书虽然是入门教材，但也足足有100多页。我对它做了一个详细的笔记，试图理清jQuery的设计思想，找出学习的脉络。我的目标是全面掌握jQuery，遇到问题的时候，心里有底，基本知道使用它的哪一个功能，然后可以迅速从手册中找到具体的写法。&#xD;
&#xD;
下面就是我的笔记，它应该是目前网上不多的jQuery中文教程之一。你只需要一点javascript语言的基本知识，就能看懂它，在最短的时间里，掌握jQuery的所有主要方面（除了ajax和插件开发）。&#xD;
&#xD;
===========================================&#xD;
&#xD;
jQuery设计思想&#xD;
&#xD;
原文网址：http://jqfundamentals.com/book/&#xD;
&#xD;
阮一峰 翻译整理&#xD;
&#xD;
【目录】&#xD;
&#xD;
　　一、选择网页元素&#xD;
&#xD;
　　二、改变结果集&#xD;
&#xD;
　　三、链式操作&#xD;
&#xD;
　　四、元素的操作：取值和赋值&#xD;
&#xD;
　　五、元素的操作：移动&#xD;
&#xD;
　　六、元素的操作：复制、删除和创建&#xD;
&#xD;
　　七、工具方法&#xD;
&#xD;
　　八、事件操作&#xD;
&#xD;
　　九、特殊效果&#xD;
&#xD;
【正文】&#xD;
&#xD;
一、选择网页元素&#xD;
&#xD;
jQuery的基本设计和主要用法，就是"选择某个网页元素，然后对其进行某种操作"。这是它区别于其他函数库的根本特点。&#xD;
&#xD;
使用jQuery的第一步，往往就是将一个选择表达式，放进构造函数jQuery()（简写为$），然后得到被选中的元素。&#xD;
&#xD;
选择表达式可以是CSS选择器：&#xD;
&#xD;
　　$(document) //选择整个文档对象&#xD;
&#xD;
　　$('#myId') //选择ID为myId的网页元素&#xD;
&#xD;
　　$('div.myClass') // 选择class为myClass的div元素&#xD;
&#xD;
　　$('input[name=first]') // 选择name属性等于first的input元素&#xD;
&#xD;
也可以是jQuery特有的表达式：&#xD;
&#xD;
　　$('a:first') //选择网页中第一个a元素&#xD;
&#xD;
　　$('tr:odd') //选择表格的奇数行&#xD;
&#xD;
　　$('#myForm :input') // 选择表单中的input元素&#xD;
&#xD;
　　$('div:visible') //选择可见的div元素&#xD;
&#xD;
　　$('div:gt(2)') // 选择所有的div元素，除了前三个&#xD;
&#xD;
　　$('div:animated') // 选择当前处于动画状态的div元素&#xD;
&#xD;
二、改变结果集&#xD;
&#xD;
如果选中多个元素，jQuery提供过滤器，可以缩小结果集：&#xD;
&#xD;
　　$('div').has('p'); // 选择包含p元素的div元素&#xD;
&#xD;
　　$('div').not('.myClass'); //选择class不等于myClass的div元素&#xD;
&#xD;
　　$('div').filter('.myClass'); //选择class等于myClass的div元素&#xD;
&#xD;
　　$('div').first(); //选择第1个div元素&#xD;
&#xD;
　　$('div').eq(5); //选择第6个div元素&#xD;
&#xD;
有时候，我们需要从结果集出发，移动到附近的相关元素，jQuery也提供了在DOM树上的移动方法：&#xD;
&#xD;
　　$('div').next('p'); //选择div元素后面的第一个p元素&#xD;
&#xD;
　　$('div').parent(); //选择div元素的父元素&#xD;
&#xD;
　　$('div').closest('form'); //选择离div最近的那个form父元素&#xD;
&#xD;
　　$('div').children(); //选择div的所有子元素&#xD;
&#xD;
　　$('div').siblings(); //选择div的同级元素&#xD;
&#xD;
三、链式操作&#xD;
&#xD;
选中网页元素以后，就可以对它进行某种操作。&#xD;
&#xD;
jQuery允许将所有操作连接在一起，以链条的形式写出来，比如：&#xD;
&#xD;
　　$('div').find('h3').eq(2).html('Hello');&#xD;
&#xD;
分解开来，就是下面这样：&#xD;
&#xD;
　　$('div') //找到div元素&#xD;
&#xD;
　　　.find('h3') //选择其中的h3元素&#xD;
&#xD;
　　　.eq(2) //选择第3个h3元素&#xD;
&#xD;
　　　.html('Hello'); //将它的内容改为Hello&#xD;
&#xD;
这是jQuery最令人称道、最方便的特点。它的原理在于每一步的jQuery操作，返回的都是一个jQuery对象，所以不同操作可以连在一起。&#xD;
&#xD;
jQuery还提供了.end()方法，使得结果集可以后退一步：&#xD;
&#xD;
　　$('div') &#xD;
&#xD;
　　　.find('h3')&#xD;
&#xD;
　　　.eq(2)&#xD;
&#xD;
　　　.html('Hello')&#xD;
&#xD;
　　　.end() //退回到选中所有的h3元素的那一步&#xD;
&#xD;
　　　.eq(0) //选中第一个h3元素&#xD;
&#xD;
　　　.html('World'); //将它的内容改为World&#xD;
&#xD;
四、元素的操作：取值和赋值&#xD;
&#xD;
操作网页元素，最常见的需求是取得它们的值，或者对它们进行赋值。&#xD;
&#xD;
jQuery使用同一个函数，来完成取值（getter）和赋值（setter）。到底是取值还是赋值，由函数的参数决定。&#xD;
&#xD;
　　$('h1').html(); //html()没有参数，表示取出h1的值&#xD;
&#xD;
　　$('h1').html('Hello'); //html()有参数Hello，表示对h1进行赋值&#xD;
&#xD;
常见的取值和赋值函数如下：&#xD;
&#xD;
　　.html() 取出或设置html内容&#xD;
&#xD;
　　.text() 取出或设置text内容&#xD;
&#xD;
　　.attr() 取出或设置某个属性的值&#xD;
&#xD;
　　.width() 取出或设置某个元素的宽度&#xD;
&#xD;
　　.height() 取出或设置某个元素的高度&#xD;
&#xD;
　　.val() 取出某个表单元素的值&#xD;
&#xD;
需要注意的是，如果结果集包含多个元素，那么赋值的时候，将对其中所有的元素赋值；取值的时候，则是只取出第一个元素的值（.text()例外，它取出所有元素的text内容）。&#xD;
&#xD;
五、元素的操作：移动&#xD;
&#xD;
如果要移动选中的元素，有两种方法：一种是直接移动该元素，另一种是移动其他元素，使得目标元素达到我们想要的位置。&#xD;
&#xD;
假定我们选中了一个div元素，需要把它移动到p元素后面。&#xD;
&#xD;
第一种方法是使用.insertAfter()，把div元素移动p元素后面：&#xD;
&#xD;
　　$('div').insertAfter('p');&#xD;
&#xD;
第二种方法是使用.after()，把p元素加到div元素前面：&#xD;
&#xD;
　　$('p').after('div');&#xD;
&#xD;
表面上看，这两种方法的效果是一样的，唯一的不同似乎只是操作视角的不同。但是实际上，它们有一个重大差别，那就是返回的元素不一样。第一种方法返回div元素，第二种方法返回p元素。你可以根据需要，选择到底使用哪一种方法。&#xD;
&#xD;
使用这种模式的操作方法，一共有四对：&#xD;
&#xD;
　　.insertAfter()和.after()：在现存元素的外部，从后面插入元素&#xD;
&#xD;
　　.insertBefore()和.before()：在现存元素的外部，从前面插入元素&#xD;
&#xD;
　　.appendTo()和.append()：在现存元素的内部，从后面插入元素&#xD;
&#xD;
　　.prependTo()和.prepend()：在现存元素的内部，从前面插入元素&#xD;
&#xD;
六、元素的操作：复制、删除和创建&#xD;
&#xD;
复制元素使用.clone()。&#xD;
&#xD;
删除元素使用.remove()和.detach()。两者的区别在于，前者不保留被删除元素的事件，后者保留，有利于重新插入文档时使用。&#xD;
&#xD;
清空元素内容（但是不删除该元素）使用.empty()。&#xD;
&#xD;
创建新元素的方法非常简单，只要把新元素直接传入jQuery的构造函数就行了：&#xD;
&#xD;
　　$('&lt;p&gt;Hello&lt;/p&gt;');&#xD;
&#xD;
　　$('&lt;li &gt;new list item&lt;/li&gt;');&#xD;
&#xD;
　　$('ul').append('&lt;li&gt;list item&lt;/li&gt;');&#xD;
&#xD;
七、工具方法&#xD;
&#xD;
除了对选中的元素进行操作以外，jQuery还提供一些工具方法（utility），不必选中元素，就可以直接使用。&#xD;
&#xD;
如果你懂得Javascript语言的继承原理，那么就能理解工具方法的实质。它是定义在jQuery构造函数上的方法，即jQuery.method()，所以可以直接使用。而那些操作元素的方法，是定义在构造函数的prototype对象上的方法，即jQuery.prototype.method()，所以必须生成实例（即选中元素）后使用。如果不理解这种区别，问题也不大，只要把工具方法理解成，是像javascript原生函数那样，可以直接使用的方法就行了。&#xD;
&#xD;
常用的工具方法有以下几种：&#xD;
&#xD;
　　$.trim() 去除字符串两端的空格。&#xD;
&#xD;
　　$.each() 遍历一个数组或对象。&#xD;
&#xD;
　　$.inArray() 返回一个值在数组中的索引位置。如果该值不在数组中，则返回-1。&#xD;
&#xD;
　　$.grep() 返回数组中符合某种标准的元素。&#xD;
&#xD;
　　$.extend() 将多个对象，合并到第一个对象。&#xD;
&#xD;
　　$.makeArray() 将对象转化为数组。&#xD;
&#xD;
　　$.type() 判断对象的类别（函数对象、日期对象、数组对象、正则对象等等）。&#xD;
&#xD;
　　$.isArray() 判断某个参数是否为数组。&#xD;
&#xD;
　　$.isEmptyObject() 判断某个对象是否为空（不含有任何属性）。&#xD;
&#xD;
　　$.isFunction() 判断某个参数是否为函数。&#xD;
&#xD;
　　$.isPlainObject() 判断某个参数是否为用"{}"或"new Object"建立的对象。&#xD;
&#xD;
　　$.support() 判断浏览器是否支持某个特性。&#xD;
&#xD;
八、事件操作&#xD;
&#xD;
jQuery可以对网页元素绑定事件。根据不同的事件，运行相应的函数。&#xD;
&#xD;
　　$('p').click(function(){&#xD;
&#xD;
　　　　alert('Hello');&#xD;
&#xD;
　　});&#xD;
&#xD;
目前，jQuery主要支持以下事件：&#xD;
&#xD;
　　.blur() 表单元素失去焦点。&#xD;
&#xD;
　　.change() 表单元素的值发生变化&#xD;
&#xD;
　　.click() 鼠标单击&#xD;
&#xD;
　　.dblclick() 鼠标双击&#xD;
&#xD;
　　.focus() 表单元素获得焦点&#xD;
&#xD;
　　.focusin() 子元素获得焦点&#xD;
&#xD;
　　.focusout() 子元素失去焦点 &#xD;
&#xD;
　　.hover() 同时为mouseenter和mouseleave事件指定处理函数&#xD;
&#xD;
　　.keydown() 按下键盘（长时间按键，只返回一个事件）&#xD;
&#xD;
　　.keypress() 按下键盘（长时间按键，将返回多个事件）&#xD;
&#xD;
　　.keyup() 松开键盘&#xD;
&#xD;
　　.load() 元素加载完毕&#xD;
&#xD;
　　.mousedown() 按下鼠标 &#xD;
&#xD;
　　.mouseenter() 鼠标进入（进入子元素不触发）&#xD;
&#xD;
　　.mouseleave() 鼠标离开（离开子元素不触发）&#xD;
&#xD;
　　.mousemove() 鼠标在元素内部移动&#xD;
&#xD;
　　.mouseout() 鼠标离开（离开子元素也触发）&#xD;
&#xD;
　　.mouseover() 鼠标进入（进入子元素也触发）&#xD;
&#xD;
　　.mouseup() 松开鼠标&#xD;
&#xD;
　　.ready() DOM加载完成&#xD;
&#xD;
　　.resize() 浏览器窗口的大小发生改变&#xD;
&#xD;
　　.scroll() 滚动条的位置发生变化&#xD;
&#xD;
　　.select() 用户选中文本框中的内容&#xD;
&#xD;
　　.submit() 用户递交表单&#xD;
&#xD;
　　.toggle() 根据鼠标点击的次数，依次运行多个函数&#xD;
&#xD;
　　.unload() 用户离开页面&#xD;
&#xD;
以上这些事件在jQuery内部，都是.bind()的便捷方式。使用.bind()可以更灵活地控制事件，比如为多个事件绑定同一个函数：&#xD;
&#xD;
　　$('input').bind(&#xD;
&#xD;
　　　　'click change', //同时绑定click和change事件&#xD;
&#xD;
　　　　function() {&#xD;
&#xD;
　　　　　　alert('Hello');&#xD;
&#xD;
　　　　}&#xD;
&#xD;
　　);&#xD;
&#xD;
有时，你只想让事件运行一次，这时可以使用.one()方法。&#xD;
&#xD;
　　$("p").one("click", function() {&#xD;
&#xD;
　　　　alert("Hello"); //只运行一次，以后的点击不会运行&#xD;
&#xD;
　　});&#xD;
&#xD;
.unbind()用来解除事件绑定。&#xD;
&#xD;
　　$('p').unbind('click');&#xD;
&#xD;
所有的事件处理函数，都可以接受一个事件对象（event object）作为参数，比如下面例子中的e：&#xD;
&#xD;
　　$("p").click(function(e) {&#xD;
&#xD;
　　　　alert(e.type); // "click"&#xD;
&#xD;
　　});&#xD;
&#xD;
这个事件对象有一些很有用的属性和方法：&#xD;
&#xD;
　　event.pageX 事件发生时，鼠标距离网页左上角的水平距离&#xD;
&#xD;
　　event.pageY 事件发生时，鼠标距离网页左上角的垂直距离&#xD;
&#xD;
　　event.type 事件的类型（比如click）&#xD;
&#xD;
　　event.which 按下了哪一个键&#xD;
&#xD;
　　event.data 在事件对象上绑定数据，然后传入事件处理函数&#xD;
&#xD;
　　event.target 事件针对的网页元素&#xD;
&#xD;
　　event.preventDefault() 阻止事件的默认行为（比如点击链接，会自动打开新页面）&#xD;
&#xD;
　　event.stopPropagation() 停止事件向上层元素冒泡&#xD;
&#xD;
在事件处理函数中，可以用this关键字，返回事件针对的DOM元素：&#xD;
&#xD;
　　$('a').click(function() {&#xD;
&#xD;
　　　　if ($(this).attr('href').match('evil')) { //如果确认为有害链接&#xD;
&#xD;
　　　　　　e.preventDefault(); //阻止打开&#xD;
&#xD;
　　　　　　$(this).addClass('evil'); //加上表示有害的class&#xD;
&#xD;
　　　　}&#xD;
&#xD;
　　});&#xD;
&#xD;
有两种方法，可以自动触发一个事件。一种是直接使用事件函数，另一种是使用.trigger()或.triggerHandler()。&#xD;
&#xD;
　　$('a').click();&#xD;
&#xD;
　　$('a').trigger('click');&#xD;
&#xD;
九、特殊效果&#xD;
&#xD;
jQuery允许对象呈现某些特殊效果。&#xD;
&#xD;
　　$('h1').show(); //展现一个h1标题&#xD;
&#xD;
常用的特殊效果如下：&#xD;
&#xD;
　　.fadeIn() 淡入&#xD;
&#xD;
　　.fadeOut() 淡出&#xD;
&#xD;
　　.fadeTo() 调整透明度&#xD;
&#xD;
　　.hide() 隐藏元素&#xD;
&#xD;
　　.show() 显示元素&#xD;
&#xD;
　　.slideDown() 向下展开&#xD;
&#xD;
　　.slideUp() 向上卷起&#xD;
&#xD;
　　.slideToggle() 依次展开或卷起某个元素&#xD;
&#xD;
　　.toggle() 依次展示或隐藏某个元素&#xD;
&#xD;
除了.show()和.hide()，所有其他特效的默认执行时间都是400ms（毫秒），但是你可以改变这个设置。&#xD;
&#xD;
　　$('h1').fadeIn(300); // 300毫秒内淡入&#xD;
&#xD;
　　$('h1').fadeOut('slow'); // 缓慢地淡出&#xD;
&#xD;
在特效结束后，可以指定执行某个函数。&#xD;
&#xD;
　　$('p').fadeOut(300, function() { $(this).remove(); });&#xD;
&#xD;
更复杂的特效，可以用.animate()自定义。&#xD;
&#xD;
　　$('div').animate(&#xD;
&#xD;
　　　　{&#xD;
&#xD;
　　　　　　left : "+=50", //不断右移&#xD;
&#xD;
　　　　　　opacity : 0.25 //指定透明度&#xD;
&#xD;
　　　　},&#xD;
&#xD;
　　　　300, // 持续时间&#xD;
&#xD;
　　　　function() { alert('done!'); } //回调函数&#xD;
&#xD;
　　);&#xD;
&#xD;
.stop()和.delay()用来停止或延缓特效的执行。&#xD;
&#xD;
$.fx.off如果设置为true，则关闭所有网页特效。&#xD;
&lt;img src="http://www.cnblogs.com/h-hello/aggbug/2130299.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/2130299.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1987868.html</id><title type="text">漫谈C语言及如何学习C语言</title><summary type="text">云风最近写了一篇博客《C语言的前世今生》。作为长期使用C语言开发网络游戏服务器的程序员，云风是有理由写这样一篇文字，不过还是感觉谈的不够深入，C语言在业界使用的现状没有怎么描写，有些意犹未尽。在这里想比较系统的谈谈个人对C语言学习方式方法的理解。分别按照书籍、实验环境搭建、网络资源来分别介绍，希望能写的比较完整全面一些，给想学习C语言的朋友一个有价值的参考。为什么要学习C语言？为什么要学习、使用C语言？为什么要学习一个可能比自己都岁数大的编程语言？我在前面如何学习编程语言的博客文章http://sunxiunan.com/?p=1597 里提到，选择一门编程语言，“为什么而学”这个目的是最重要</summary><published>2011-03-18T03:19:00Z</published><updated>2011-03-18T03:19:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1987868.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1987868.html"/><content type="html">&lt;div &gt;&#xD;
&lt;p&gt;云风最近写了一篇博客《&lt;a href="http://blog.codingnow.com/2010/06/c_programming_language.html#more" target="_blank"&gt;C语言的前世今生&lt;/a&gt;》。作为长期使用C语言开发网络游戏服务器的程序员，云风是有理由写这样一篇文字，不过还是感觉谈的不够深入，C语言在业界使用的现状没有怎么描写，有些意犹未尽。&lt;/p&gt;&#xD;
&lt;p&gt;在这里想比较系统的谈谈个人对C语言学习方式方法的理解。分别按照书籍、实验环境搭建、网络资源来分别介绍，希望能写的比较完整全面一些，给想学习C语言的朋友一个有价值的参考。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;为什么要学习C语言？&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;为什么要学习、使用C语言？为什么要学习一个可能比自己都岁数大的编程语言？&lt;/p&gt;&#xD;
&lt;p&gt;我在前面如何学习编程语言的博客文章&lt;a title="http://sunxiunan.com/?p=1597" href="http://sunxiunan.com/?p=1597"&gt;http://sunxiunan.com/?p=1597&lt;/a&gt;&#xD;
 &#xD;
里提到，选择一门编程语言，&amp;ldquo;为什么而学&amp;rdquo;这个目的是最重要的，目的不明确就没法学好。这也是为什么很多学生朋友在大学里必修C语言却觉得没学明白的原&#xD;
因。因为学习的目的不明确，学习当然也没有动力。还有一个原因是C语言是工程实践性很强的语言，它不是来自某个研究所某个大学学院，而是实实在在从项目需&#xD;
要中产生，伴随着Unix的兴起而流行，语义简明清晰，功能强大而不臃肿，简洁而又不过分简单，实在是居家旅行工作学习必备之良友。&lt;/p&gt;&#xD;
&lt;p&gt;C语言相比C++的优点之一就是最小惊讶原则，一是一二是二，不会在私底下产生一些莫名其妙的额外产物。用C++做个例子，比如这样一个函数原型&#xD;
void PassWithClassValue(COneClass &#xD;
clsParam1)，稍微了解C++的朋友都会知道，如果你没有实现COneClass的拷贝构造函数，编译器会好心的帮你实现一个，而且在调用这个函&#xD;
数PassWithClassValue的时候，偷偷地调用拷贝构造函数产生一个临时对象作为参数传递，对于某些情况，比如编写操作系统这类必须优化性能&#xD;
的情景下，这些自以为是的东西是非常邪恶的事情。&lt;/p&gt;&#xD;
&lt;p&gt;C语言本身只提供必要的语言特性，其它复杂一点功能如文件处理、数学计算等等都以库函数方式提供，甚至连malloc、free这种&amp;ldquo;必须有&amp;rdquo;的功&#xD;
能，也是以标准库函数的方式提供，而不是作为C语言核心出现。在伟大的著名的无所不包的《K&amp;amp;R》开头部分就提到了，for其实可以通过&#xD;
while来完成，只不过for可以写的更简洁，言外之意，对于C语言for其实不是必要的。跑题一点说，在其它程序语言中Lua可以说继承了C语言简洁&#xD;
的设计哲学，甚至连continue这种几乎必备的关键字都一直拒绝加入，在Lua的maillist以及wiki里都提到过continue这个问&#xD;
题，Lua语言维护者认为continue对于Lua而言不是必要的，也不考虑在后续版本中添加这个关键字。这种简洁哲学也让C语言的可移植性、便携性特&#xD;
别优秀，也使得很多嵌入式系统依然使用C语言作为主要编程工作语言。&lt;/p&gt;&#xD;
&lt;p&gt;Java语言有一个口号：&amp;ldquo;一次编写，处处运行&amp;rdquo;，就是跨平台这个噱头。实际上C语言从早期开始就几乎达到了&amp;ldquo;一次编写，处处编译&amp;rdquo;，在ANSI在&#xD;
1989年统一了C语言标准以后（称之为C89），只要特定平台上的编译器完整实现了C89标准，而且你的代码没有使用某些特殊的扩展（GCC以及微软都&#xD;
有自己的编译器特定扩展），那么代码一定可以编译通过，再实现一下操作系统相关的函数库，C语言的移植就是很简单的事情。可以用Lua作为例子，Lua本&#xD;
身是完全遵循C89标准，没有使用任何特定扩展，这也保证了有C语言编译器的平台，都可以编译使用Lua。可以编译运行C语言的硬件平台可以从A排到Z，&#xD;
真是非常有意思的事情。&lt;/p&gt;&#xD;
&lt;p&gt;C语言也是一个比较少见的应用领域极为广泛的语言。比如编写操作系统这种高难问题，只有C++、汇编语言可以做到。C语言可以编写服务器端软件如&#xD;
Apache、Nginx，或者编写GUI程序，如GTK。大多数程序语言的第一版是通过C语言实现，借助前面提到的&amp;ldquo;一次编写处处编译&amp;rdquo;，最大的保证了&#xD;
这些程序语言的可移植性。在Web开发领域，C语言的应用相对较少，这也是一种取舍的结果，Web开发需要使用PHP、Ruby、Python这样的动态&#xD;
语言，可以快速上线快速修改，可以最大程度满足用户时时变化的需求，这也是C语言的弱项。如果把程序语言的应用领域从硬件到管理软件、Web程序做一个很&#xD;
粗略从下到上的排列，C语言适合领域是比较底层靠近硬件的部分，而新兴语言比较偏重于高层管理或者Web开发这种相对贴近最终用户的领域。比较流行的混合&#xD;
开发模式是使用C语言编写底层高性能部分代码或后台服务器代码，而使用动态语言如Python做前端开发，充分发挥它们各自的优势力量。&lt;/p&gt;&#xD;
&lt;p&gt;提到C语言的缺点，常常是它缺少这种或者那种特性，比如有人建议加入GC，有人建议加入并行或者并发支持，有人提到没有一个比较完整的类似C++的&#xD;
异常策略。这些特性有的可以通过引入第三方库来实现，但C语言的设计哲学其实决定了它不会像C++那样&amp;ldquo;非常强大&amp;rdquo;。即使引入了某些人期望的特性，依然会&#xD;
是某些人喜欢某些人不喜欢的情形，现在的功能对于C语言应用领域来说已经够用，其它特性可以通过特定程序语言实现，并且通过C &#xD;
API与C语言编写的程序进行交互。任何一个工匠都不可能只使用一个工具完成他的工作，不同工具结合起来才能更快更好的完成任务。&lt;/p&gt;&#xD;
&lt;p&gt;提到C &#xD;
API，也稍微介绍一下，我们知道windows操作系统的api也好，Linux的系统api也好，或者是想给Ruby、Python编写扩展模块，C&#xD;
语言形式的函数定义都是唯一的选择。C语言就好像是一个中间层或者是胶水，如果想把不同编程语言实现的功能模块混合使用，C语言是最佳的选择。&lt;/p&gt;&#xD;
&lt;p&gt;提了这么多关于C语言的好处，那么学习C语言是否适合就看你自己的判断了，例如要进行一个嵌入式项目，或者需要进行服务器端开发，或者写一个性能相&#xD;
关的组件等等，C语言都是比较好用的选择。另外也可以在C++的使用过程中有意的使用C语言的思考方式，汲取C语言简洁明快清晰地设计思路，对编程设计水&#xD;
平会有很大的提高。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;C语言学习方法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在前面&lt;a title="http://sunxiunan.com/?p=1597" href="http://sunxiunan.com/?p=1597"&gt;http://sunxiunan.com/?p=1597&lt;/a&gt; 曾经提到过一个比较系统学习一门新的编程语言的方式，C语言学习也可以按照类似的顺序：阅读参考书，阅读代码，编写调试实际程序，上网参与讨论，研究高级话题。&lt;/p&gt;&#xD;
&lt;p&gt;学习语言的开始一般是阅读参考书。我建议选择几本非常经典的好书，仔细完整反复阅读几遍，&amp;ldquo;书读百遍其义自现&amp;rdquo;。选择C语言学习的好处是，这几本书基本上完整涵盖了C语言编程领域的方方面面，不会像C++那样，即使读完一堆书还是有些糊涂，依然有这样那样难懂的陷阱。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1，参考书籍&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在豆瓣上列了一个书单，大家可以直接参考&lt;a title="http://book.douban.com/doulist/636329/" href="http://book.douban.com/doulist/636329/"&gt;http://book.douban.com/doulist/636329/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在下面简单点评一下，阅读顺序最好参照列出的顺序。&lt;/p&gt;&#xD;
&lt;p&gt;《The C Programming Language》&lt;a title="http://book.douban.com/subject/1230004/" href="http://book.douban.com/subject/1230004/"&gt;http://book.douban.com/subject/1230004/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb.png" alt="image" align="right" border="0" height="232" width="178" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果你只想买一本书学习C语言，只需要买这一本就够了。如果你经费足够，建议你多买几本，办公室、家里都放上一本，随手都可以翻翻。用三个词语来形&#xD;
容它就是：经典！经典！经典！这本薄薄的只有二百多页的小书涵盖了C语言的方方面面，前无古人而且后无来者，任何溢美之词都不足以形容它。&lt;/p&gt;&#xD;
&lt;p&gt;《The C Programming Language》（后面称为 &#xD;
K&amp;amp;R）里面包含了一个简单的语法解析器，包含了malloc如何实现，包含了一个完整的操作系统目录浏览程序，这些程序的实用性极高，可以这样&#xD;
说，如果学习任何一门语言能够自己独立动手实现以上的功能，基本上就可以算是入门了。K&amp;amp;R书里面每段都蕴含着非常值得探究的软件开发工程实践经&#xD;
验，如果没有一定的开发经验，其实是看不出来这些冰山下面的内容的，比如开头一章就提出用写完整代码这种方式来教学，而在书中那些C语言的陷阱或者可能出&#xD;
问题的地方，都有提到，但是由于篇幅所限，写的非常简约，很难让人一下就看懂。我正在完整的逐字逐句的阅读此书，希望能稍作注解，写几篇博客分享一下。&lt;/p&gt;&#xD;
&lt;p&gt;《C程序设计语言（第2版&amp;middot;新版）》&lt;a title="http://book.douban.com/subject/1139336/" href="http://book.douban.com/subject/1139336/"&gt;http://book.douban.com/subject/1139336/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这是K&amp;amp;R的中文译本，可以先从中文译本看起，然后再读一遍英文原版，既可以学习英文，又可以体会原文那种简约优美的风格。&lt;/p&gt;&#xD;
&lt;p&gt;《C陷阱与缺陷》&lt;a title="http://book.douban.com/subject/2778632/" href="http://book.douban.com/subject/2778632/"&gt;http://book.douban.com/subject/2778632/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《C专家编程》&lt;a title="http://book.douban.com/subject/2377310/" href="http://book.douban.com/subject/2377310/"&gt;http://book.douban.com/subject/2377310/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这两本书也是学习及使用C语言的朋友必备的两本书，比如《C专家编程》，专门用两三个章节详细介绍C语言中数组与指针的不同之处，这两本书在某种程度上算是对K&amp;amp;R略过的地方做了详细补充，强烈推荐。&lt;/p&gt;&#xD;
&lt;p&gt;《C语言参考手册》&lt;a title="http://book.douban.com/subject/2132084/" href="http://book.douban.com/subject/2132084/"&gt;http://book.douban.com/subject/2132084/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这是最后一本强烈推荐你最好买回家作为案头书必备的参考书。前面几本书或者稍显简略，或者专注某个特定专题，都不适合遇到问题时翻查。这本《C语言参考手册》可以看作是C语言编程的《新华字典》，全面而权威。里面还涵盖了C99的内容，紧跟时代潮流。&lt;/p&gt;&#xD;
&lt;p&gt;下面几本书都可以作为交叉参考，也都很有价值，也是建议大家都买下来，好书如朋友，日久弥新，像是我推荐的这几本书在douban或者amazon上评分都非常高，而且反复再版。&lt;/p&gt;&#xD;
&lt;p&gt;《C和指针》&lt;a title="http://book.douban.com/subject/1229973/" href="http://book.douban.com/subject/1229973/"&gt;http://book.douban.com/subject/1229973/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;指针的重要性如何，学过C语言（或者C++）的朋友都知道，这本书更是把指针拔高到了与C语言平起平坐的地位，其实也是从头开始介绍，作为教学参考书也是可以的。&lt;/p&gt;&#xD;
&lt;p&gt;《C标准库》&lt;a title="http://book.douban.com/subject/3775842/" href="http://book.douban.com/subject/3775842/"&gt;http://book.douban.com/subject/3775842/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这本书是专门介绍C语言的标准库如何实现的，比如malloc算法，用标准的C语言该如何写？strlen这个函数应该如何实现？尽管书中不少代码与真实的C标准库相差很多（由于标准库需要考虑性能优化，很多函数有一些特定的trick），但是绝对值得参考。&lt;/p&gt;&#xD;
&lt;p&gt;《你必须知道的495个C语言问题》 &lt;a title="http://book.douban.com/subject/3422332/" href="http://book.douban.com/subject/3422332/"&gt;http://book.douban.com/subject/3422332/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这本书其实就是C-FAQ的印刷版本，C-FAQ在各种编程语言的FAQ中可以称得上质量一流。如果你想应聘或者招聘C语言相关程序员，这本书一定要参考。&lt;/p&gt;&#xD;
&lt;p&gt;《Linux C编程一站式学习》&lt;a title="http://book.douban.com/subject/4141733/" href="http://book.douban.com/subject/4141733/"&gt;http://book.douban.com/subject/4141733/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这本书是基于特定操作系统Linux来介绍C语言编程，可作为计算机相关专业的教科书或入门参考书，也是书单里面唯一一本国人原创的编程书籍，非常难得。书中几乎所有内容都在网上直接公开，针对读者的意见进行修改，这也是非常难得的一种开放态度。非常推荐大家买一本。&lt;/p&gt;&#xD;
&lt;p&gt;学习C语言，一定不能只读书，应该动手练习完成书里面的项目需求（比如编写一个目录浏览器）以及每章的练习题目。这就需要有可以实验的环境，下面针对不同操作系统简单做一下介绍。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2，动手实验环境搭建&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;也没有调查过，不知道现在学校里学习C语言是不是依然跟着谭浩强老师用TurboC2.0编程，如果还是这个组合的话，那就太差劲了，赶快抛开它们。&lt;/p&gt;&#xD;
&lt;p&gt;下面主要介绍不同操作系统平台下的集成编程环境，基于初学者以及我个人喜好，就不推荐大家命令行下用vim编程了，直接上IDE。&lt;/p&gt;&#xD;
&lt;p&gt;Windows系统下推荐大家使用Code::blocks这个软件。这个软件最大优点是自带了基于mingw的GCC以及GDB，只要下载70M&#xD;
左右软件包，就可以完整支持C++、C语言编程了。各种功能（比如调试功能）也很强大，版本更新也比较快。注意下载选择名字有mingw的文件，比如最新&#xD;
版本是codeblocks-10.05mingw-setup.exe（版本也许有所不同）。&lt;/p&gt;&#xD;
&lt;p&gt;主页：&lt;a title="http://www.codeblocks.org/" href="http://www.codeblocks.org/"&gt;http://www.codeblocks.org/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image_3.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb_3.png" alt="image" border="0" height="265" width="320" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果需要做Windows操作系统的开发，可以下载Visual C++ 2010 Express。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image_4.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb_4.png" alt="image" border="0" height="280" width="340" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;因为Code::Blocks不包含Windows编程头文件（实际是因为没有Windows &#xD;
SDK），无法编写Windows操作系统相关的界面应用程序或者服务类程序。而VC++Express自带了这些头文件以及编程库，虽然功能稍微简陋，&#xD;
但对于练习使用基本够用。&lt;/p&gt;&#xD;
&lt;p&gt;主页：&lt;a title="http://www.microsoft.com/express/windows/" href="http://www.microsoft.com/express/windows/"&gt;http://www.microsoft.com/express/windows/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;对于计算机专业的学生朋友，建议大家使用Linux操作系统，或者更详细一点是使用Xubuntu操作系统作为桌面，使用Netbeans和GCC&#xD;
这个组合（当然也可以选择Code::Blocks）。在Xubuntu下可以通过apt-get install &#xD;
build-essential这个命令安装gcc相关程序，已经可以在Terminal下编译C语言程序了，但为了使用方便，大家可以选择&#xD;
Netbeans的C++支持包，在Netbeans网站上就能下载。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image_5.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb_5.png" alt="image" border="0" height="194" width="504" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;主页：&lt;a title="http://netbeans.org/features/cpp/index.html" href="http://netbeans.org/features/cpp/index.html"&gt;http://netbeans.org/features/cpp/index.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果使用苹果Mac系统，毫无疑问XCode就是编程的绝佳选择，XCode可以在苹果开发者网站上免费下载，在IPhone SDK中也包含了XCode。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image_6.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb_6.png" alt="image" border="0" height="328" width="381" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;主页：&lt;a title="http://developer.apple.com/technologies/tools/xcode.html" href="http://developer.apple.com/technologies/tools/xcode.html"&gt;http://developer.apple.com/technologies/tools/xcode.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果手头没有合适的编程环境，还需要实验一些简单的代码，可以用&lt;a title="http://codepad.org/" href="http://codepad.org/"&gt;http://codepad.org/&lt;/a&gt; 提供的服务，在线编写运行代码。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://sunxiunan.com/media/C_8803/image_7.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" src="http://sunxiunan.com/media/C_8803/image_thumb_7.png" alt="image" border="0" height="488" width="375" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;另外建议大家申请一个github.com的账号，在gist.github.com可以保存自己的练习代码，就不需要随身带着U盘了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3，网络资源&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果想用十分钟时间了解一下C语言的来龙去脉、前世今生，维基百科这个页面&lt;a title="http://en.wikipedia.org/wiki/C_%28programming_language%29" href="http://en.wikipedia.org/wiki/C_%28programming_language%29"&gt;http://en.wikipedia.org/wiki/C_%28programming_language%29&lt;/a&gt; 是最佳选择。&lt;/p&gt;&#xD;
&lt;p&gt;从维基百科可以看到，C语言1972年由Dennis &#xD;
Ritchie设计的命令式、结构化范式编程语言。类型为静态的弱类型，需要显式定义。最新国际标准为C99。设计上主要受到了B、ALGOL68、汇编&#xD;
语言、PL/I、FORTRAN的影响，C语言也影响了大量编程语言，如C++、Objective-C、C#、Java、Go、PHP、Python等&#xD;
等（个人觉得受C影响很大的是PHP，基本上有C编程基础的程序员，很容易就能上手PHP了，除了PHP的OO部分）。&lt;/p&gt;&#xD;
&lt;p&gt;在维基百科条目中有很大篇幅介绍了作者认为C语言缺失的特性，比如面向对象、多线程、GC、异常处理等等，当然这有些吹毛求疵，如果需要这些特性，&#xD;
完全可以用其它程序语言。另外一个介绍的重点是&amp;ldquo;未定义行为&amp;rdquo;，有些我们认为理所当然的结果，其实在C语言标准中并没有明确定义，假定这些行为应该如何，&#xD;
当程序使用另外的编译器或者不同版本编译器编译运行，都可能有bug产生。&lt;/p&gt;&#xD;
&lt;p&gt;接下来维基百科条目谈到了C语言的用处，必须承认尽管现在编程语言成百上千，能称之为&amp;ldquo;系统级&amp;rdquo;的少之又少，新兴语言中只有Go还能称得上。现在大&#xD;
规模软件项目中完全选用C语言可能性不大，但是核心部分完全可以用C搭建，相对C++开发工具的高昂价格，C语言相关的免费辅助开发软件非常丰富，比如&#xD;
splint，valgrind，不少核心库经过长期使用也都非常稳定。&lt;/p&gt;&#xD;
&lt;p&gt;由于C语言广泛支持各种平台以及编译器相对成熟可靠，不少编程语言选择C语言作为一个中间层，比如Glasgow Haskell编译器就是这样做的。&lt;/p&gt;&#xD;
&lt;p&gt;另一个可以找到大量C语言编程相关资料的地方是&amp;ldquo;美味书签&amp;rdquo;，通过搜索特定关键字 （C + programming）就可以找到很多值得挖掘的资源&lt;a title="http://delicious.com/search?p=c+programming&amp;amp;chk=&amp;amp;context=all||&amp;amp;fr=del_icio_us&amp;amp;lc=1" href="http://delicious.com/search?p=c+programming"&gt;http://delicious.com/search?p=c+programming&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;还可以参考dmoz.org的C语言分类&lt;a title="http://www.dmoz.org/Computers/Programming/Languages/C/" href="http://www.dmoz.org/Computers/Programming/Languages/C/"&gt;http://www.dmoz.org/Computers/Programming/Languages/C/&lt;/a&gt; 相比美味书签时效性能差点，但是分类比较系统，查找也要容易一些。&lt;/p&gt;&#xD;
&lt;p&gt;程序员往往是懒惰的，&amp;ldquo;拿来主义&amp;rdquo;、&amp;ldquo;拷贝主义&amp;rdquo;很流行也很有效，当对某个函数或者关键字不是很理解的时候，看看别人是怎么使用的，会非常有启发性。这里介绍几个常用的代码搜索网站，最常用的是google的codesearch：&lt;a href="http://codesearch.google.com/"&gt;http://codesearch.google.com&lt;/a&gt; ，可以通过不同条件及正则表达式搜索特定关键词。另外可以参考维基百科上一个&amp;ldquo;&lt;a href="http://en.wikipedia.org/wiki/Category:Articles_with_example_C_code"&gt;带有C语言示例的文章&lt;/a&gt;&amp;rdquo;分类，里面代码写的也很不错。还可以在github.com上搜索相关项目。在前面博客文章我还介绍了一个名为罗塞塔代码的网站&lt;a title="http://rosettacode.org/" href="http://rosettacode.org/"&gt;http://rosettacode.org/&lt;/a&gt; 这个网站上可以找到不同程序语言针对某个问题的解决方案，用于学习比较非常便利。&lt;/p&gt;&#xD;
&lt;p&gt;学习编程也需要大量阅读名家经典代码，与学中文英文需要大量阅读名著一个道理，C语言编程优质项目那是&amp;ldquo;彩旗飘舞，人山人海&amp;rdquo;，个人建议可以看看&#xD;
Lua、Sqlite、Nginx这些项目的代码，代码量不多，而且代码质量也都比较高。另外可以看看Linux内核代码，坊间有不少书籍可以帮助解读。&#xD;
关于如何很好的阅读代码，大家可以参考《Code Reading》这本书。&lt;/p&gt;&#xD;
&lt;p&gt;书看了几本，代码写了一些，也略微读了读其他人的代码，就应该用C语言来完成真实工作中碰到的问题，让C语言真正成为你的瑞士军刀。只有当你经常使用C语言来进行编程工作，经常思考如何通过C设计一个优雅高效的系统，才能更深刻的理解C语言设计哲学。&lt;/p&gt;&#xD;
&lt;p&gt;还可以到&lt;a title="http://stackoverflow.com" href="http://stackoverflow.com/"&gt;http://stackoverflow.com&lt;/a&gt; 参与回答问题，浏览其他人的问题解答来汲取知识，比如这篇&lt;a title="http://stackoverflow.com/questions/2054939/char-is-signed-or-unsigned-by-default" href="http://stackoverflow.com/questions/2054939/char-is-signed-or-unsigned-by-default"&gt;http://stackoverflow.com/questions/2054939/char-is-signed-or-unsigned-by-default&lt;/a&gt; 就介绍了一个C语言关于char类型的小陷阱。&lt;/p&gt;&#xD;
&lt;p&gt;C语言学习当中，有一些难点需要多加注意，如pointer与array的不同之处，复杂类型定义如何解读，如何正确使用预处理preprocessor以及宏定义。其实这些内容在前面书籍都是反复提到，如果按部就班学习下来，应该不成问题。&lt;/p&gt;&#xD;
&lt;p&gt;当C语言学习的差不多时候，还可以学习一门动态语言，比如Lua或者Python，试着在实际工作项目中混合使用动态语言与C语言，一加一发挥出来的力量不仅仅是二，而是非常二（说笑一下，哈哈）。&lt;/p&gt;&#xD;
&lt;p&gt;还有什么问题，欢迎留言。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;附录&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;一些有用的C语言网络资源：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C语言标准化组织ISO JTC1/SC22/WG14的主页，在这里可以找到ISO C的文档：&lt;a title="http://www.open-std.org/jtc1/sc22/wg14/" href="http://www.open-std.org/jtc1/sc22/wg14/"&gt;http://www.open-std.org/jtc1/sc22/wg14/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《The Development of the C Language》作者Dennis Ritchie，极为经典的论文。 &lt;a title="http://cm.bell-labs.com/cm/cs/who/dmr/chist.html" href="http://cm.bell-labs.com/cm/cs/who/dmr/chist.html"&gt;http://cm.bell-labs.com/cm/cs/who/dmr/chist.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;ldquo;C语言全景&amp;rdquo;这个网站内容很全面：&lt;a title="http://www.softpanorama.org/Lang/c.shtml" href="http://www.softpanorama.org/Lang/c.shtml"&gt;http://www.softpanorama.org/Lang/c.shtml&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Dan Saks在embedded.com上的专栏&lt;a href="http://www.embedded.com/columns/archive/;jsessionid=SMLNKWF3TOUNNQE1GHPSKH4ATMY32JVN?content_type=pp" target="_blank"&gt;Programming Pointer&lt;/a&gt; ，里面文章很有深度，值得一读。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.lysator.liu.se/c/c-www.html" href="http://www.lysator.liu.se/c/c-www.html"&gt;http://www.lysator.liu.se/c/c-www.html&lt;/a&gt; 这也是一个C语言资源汇总页面。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.ioccc.org/index.html" href="http://www.ioccc.org/index.html"&gt;http://www.ioccc.org/index.html&lt;/a&gt; 混乱C语言代码大赛，很著名。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Underhanded_C_Contest" href="http://en.wikipedia.org/wiki/Underhanded_C_Contest"&gt;http://en.wikipedia.org/wiki/Underhanded_C_Contest&lt;/a&gt; 另外一个C语言编程大赛，主要面向黑客。&lt;/p&gt;&#xD;
&lt;p&gt;comp.lang.c以及c.moderated这两个讨论组推荐订阅，相当于互联网最大的C相关编程问题论坛：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://groups.google.com/group/comp.lang.c"&gt;http://groups.google.com/group/comp.lang.c&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://groups.google.com/group/comp.lang.c.moderated"&gt;http://groups.google.com/group/comp.lang.c.moderated&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这里对C语言的各种bit操作做了收集整理，不少题目在面试时候经常出现。&lt;a title="http://graphics.stanford.edu/~seander/bithacks.html" href="http://graphics.stanford.edu/%7Eseander/bithacks.html"&gt;http://graphics.stanford.edu/~seander/bithacks.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;台湾的惯C达人Jserv博客，建议大家订阅：&lt;a title="http://blog.linux.org.tw/~jserv/" href="http://blog.linux.org.tw/%7Ejserv/"&gt;http://blog.linux.org.tw/~jserv/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;一些值得关注及研究的C语言相关项目：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;TinyCC，被很多项目用作动态编译C语言的编译器引擎：&lt;a title="http://bellard.org/tcc/" href="http://bellard.org/tcc/"&gt;http://bellard.org/tcc/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;GCC的标准库实现：&lt;a title="http://en.wikipedia.org/wiki/GNU_C_Library" href="http://en.wikipedia.org/wiki/GNU_C_Library"&gt;http://en.wikipedia.org/wiki/GNU_C_Library&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Glib是GTK的底层辅助编程库，与C标准库是不一样的，在C语言上实现了面向对象机制：&lt;a title="http://en.wikipedia.org/wiki/GLib" href="http://en.wikipedia.org/wiki/GLib"&gt;http://en.wikipedia.org/wiki/GLib&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;dietlibc在前面博客文章介绍过，C标准库的另一种实现：&lt;a title="http://www.fefe.de/dietlibc/" href="http://www.fefe.de/dietlibc/"&gt;http://www.fefe.de/dietlibc/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;一些C语言编程时可以使用的工具软件，帮你提高代码质量：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.splint.org/" href="http://www.splint.org/"&gt;http://www.splint.org/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://valgrind.org/" href="http://valgrind.org/"&gt;http://valgrind.org/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.dwheeler.com/flawfinder/" href="http://www.dwheeler.com/flawfinder/"&gt;http://www.dwheeler.com/flawfinder/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;PMD可用于检测重复代码 &lt;a title="http://pmd.sourceforge.net/cpd.html" href="http://pmd.sourceforge.net/cpd.html"&gt;http://pmd.sourceforge.net/cpd.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;llvm的静态分析项目 &lt;a title="http://clang-analyzer.llvm.org/" href="http://clang-analyzer.llvm.org/"&gt;http://clang-analyzer.llvm.org/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;C语言编程规范编程标准：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/MISRA_C" href="http://en.wikipedia.org/wiki/MISRA_C"&gt;http://en.wikipedia.org/wiki/MISRA_C&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.eecs.harvard.edu/~ellard/CS50-96/programming-style.html" href="http://www.eecs.harvard.edu/%7Eellard/CS50-96/programming-style.html"&gt;http://www.eecs.harvard.edu/~ellard/CS50-96/programming-style.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://developers.sun.com/solaris/articles/secure.html" href="http://developers.sun.com/solaris/articles/secure.html"&gt;http://developers.sun.com/solaris/articles/secure.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cert这个文档国内有中文翻译版本：&lt;a title="https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Secure+Coding+Standard" href="https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Secure+Coding+Standard"&gt;https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Secure+Coding+Standard&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.cs.utah.edu/dept/old/texinfo/standards/standards_toc.html" href="http://www.cs.utah.edu/dept/old/texinfo/standards/standards_toc.html"&gt;http://www.cs.utah.edu/dept/old/texinfo/standards/standards_toc.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;C语言编程电子书及教程：&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://publications.gbdirect.co.uk/c_book/"&gt;http://publications.gbdirect.co.uk/c_book/&lt;/a&gt; 这一本写的非常详细，你可以把它看成是类似谭浩强版的教科书。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.knosof.co.uk/cbook/cbook.html"&gt;http://www.knosof.co.uk/cbook/cbook.html&lt;/a&gt; 这一本云风曾经推荐过，相当深入的介绍了C99标准，深入细节时候需要读读。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a title="http://www.duckware.com/bugfreec/index.html" href="http://www.duckware.com/bugfreec/index.html"&gt;http://www.duckware.com/bugfreec/index.html&lt;/a&gt; 这本书在网上流传一个中文版本，《编写优化、高效、无错地代码》，另外也有英文影印版《编程精粹》。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://wangcong.org/blog/?page_id=196"&gt;http://wangcong.org/blog/?page_id=196&lt;/a&gt; 作者王聪，也是相当hard geek，从两个样章看，包含了相当多的内容。&lt;/p&gt;&#xD;
&lt;p&gt;《C语言深度解剖》这本可以在百度文库或google搜到，可以读读，有些参考性。&lt;/p&gt;&#xD;
&lt;p&gt;《C标准和实现》作者姚新颜，他的《深度探索C、C++》算是当年比较有深度的书籍，可惜已经绝版了。这本书也可以在百度文库搜到。这本书也比较值得读。&lt;/p&gt;&#xD;
&lt;p&gt;良葛格C语言学习笔记 &lt;a title="http://caterpillar.onlyfun.net/Gossip/CGossip/CGossip.html" href="http://caterpillar.onlyfun.net/Gossip/CGossip/CGossip.html"&gt;http://caterpillar.onlyfun.net/Gossip/CGossip/CGossip.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C与C++的兼容性问题 &lt;a title="http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B" href="http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B"&gt;http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;另一个文档关于C与C++标准兼容性问题：&lt;a title="http://david.tribble.com/text/cdiffs.htm" href="http://david.tribble.com/text/cdiffs.htm"&gt;http://david.tribble.com/text/cdiffs.htm&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《&lt;em&gt;C Elements of Style&lt;/em&gt;》&lt;a title="http://www.oualline.com/books.free/style/index.html" href="http://www.oualline.com/books.free/style/index.html"&gt;http://www.oualline.com/books.free/style/index.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《Linux安全编程》&lt;a title="http://www.dwheeler.com/secure-programs/" href="http://www.dwheeler.com/secure-programs/"&gt;http://www.dwheeler.com/secure-programs/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《C Craft》电子版 &lt;a title="http://crypto.stanford.edu/~blynn/c/" href="http://crypto.stanford.edu/%7Eblynn/c/"&gt;http://crypto.stanford.edu/~blynn/c/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;《The function pointer tutorials》函数指针教程。&lt;a title="http://www.newty.de/fpt/index.html" href="http://www.newty.de/fpt/index.html"&gt;http://www.newty.de/fpt/index.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C语言编程及Unix系统调用，想用C在Unix或者Linux编程的朋友可以参考。&lt;a title="http://www.cs.cf.ac.uk/Dave/C/" href="http://www.cs.cf.ac.uk/Dave/C/"&gt;http://www.cs.cf.ac.uk/Dave/C/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;优化C、C++代码 &lt;a title="http://www.eventhelix.com/RealtimeMantra/Basics/OptimizingCAndCPPCode.htm" href="http://www.eventhelix.com/RealtimeMantra/Basics/OptimizingCAndCPPCode.htm"&gt;http://www.eventhelix.com/RealtimeMantra/Basics/OptimizingCAndCPPCode.htm&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;图文并茂介绍C语言的指针 &lt;a title="http://boredzo.org/pointers/" href="http://boredzo.org/pointers/"&gt;http://boredzo.org/pointers/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;另外一篇介绍C语言优化的文章 &lt;a title="http://www.prism.uvsq.fr/~cedb/local_copies/lee.html" href="http://www.prism.uvsq.fr/%7Ecedb/local_copies/lee.html"&gt;http://www.prism.uvsq.fr/~cedb/local_copies/lee.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一个C语言教学ppt &lt;a title="http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers" href="http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers"&gt;http://www.slideshare.net/petdance/just-enough-c-for-open-source-programmers&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一些Unix下C语言编程相关的文章 &lt;a title="http://users.actcom.co.il/~choo/lupg/tutorials/index.html" href="http://users.actcom.co.il/%7Echoo/lupg/tutorials/index.html"&gt;http://users.actcom.co.il/~choo/lupg/tutorials/index.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Unix下如何建立静态、动态C语言函数库 &lt;a title="http://users.actcom.co.il/~choo/lupg/tutorials/libraries/unix-c-libraries.html" href="http://users.actcom.co.il/%7Echoo/lupg/tutorials/libraries/unix-c-libraries.html"&gt;http://users.actcom.co.il/~choo/lupg/tutorials/libraries/unix-c-libraries.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如何使用GDB &lt;a title="http://users.actcom.co.il/~choo/lupg/tutorials/debugging/debugging-with-gdb.html" href="http://users.actcom.co.il/%7Echoo/lupg/tutorials/debugging/debugging-with-gdb.html"&gt;&lt;span style="text-decoration: underline;"&gt;&lt;span style="font-size: xx-small;"&gt;http://users.actcom.co.il/~choo/lupg/tutorials/debugging/debugging-with-gdb.html&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一些C语言编程技巧 &lt;a title="http://users.bestweb.net/~ctips/" href="http://users.bestweb.net/%7Ectips/"&gt;http://users.bestweb.net/~ctips/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Advanced C programming，高级C语言编程，可以提高水平，非常有帮助 &lt;a title="http://www.mpi-inf.mpg.de/departments/rg1/teaching/advancedc-ws08/literature.html" href="http://www.mpi-inf.mpg.de/departments/rg1/teaching/advancedc-ws08/literature.html"&gt;http://www.mpi-inf.mpg.de/departments/rg1/teaching/advancedc-ws08/literature.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;C语言问答，这些题目也可用于面试 &lt;a title="http://www.gowrikumar.com/c/" href="http://www.gowrikumar.com/c/"&gt;http://www.gowrikumar.com/c/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;/div&gt;&#xD;
﻿&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1987868.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1987868.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1987008.html</id><title type="text">[转]JQuery简要介绍</title><summary type="text">今年准备给OEA支持B/S，所以学一下JQuery，如果你不是像我一个是一个新手的话，那么你可以直接略过本篇。$(&amp;#39;h1&amp;#39;).html(&amp;#39;hello world&amp;#39;); $(&amp;#39;h1&amp;#39;).css({ &amp;#39;fontSize&amp;#39;: &amp;#39;100px&amp;#39;, &amp;#39;color&amp;#39;: &amp;#39;red&amp;#39;}); // setting multiple properties $(&amp;#39;h1&amp;#39;).height(&amp;#39;50px&amp;#39;); // sets the height of all H1 element</summary><published>2011-03-17T06:22:00Z</published><updated>2011-03-17T06:22:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1987008.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1987008.html"/><content type="html">今年准备给OEA支持B/S，所以学一下JQuery，如果你不是像我一个是一个新手的话，那么你可以直接略过本篇。&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162358599645.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359026557.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359059574.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359066127.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359108979.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359113025.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359199168.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359217857.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359223821.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/20110316235924558.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359288210.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359325306.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359348629.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359361222.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359401415.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359442622.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359489685.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/20110316235950293.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/20110316235953585.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103162359576535.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103170000005922.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/zhoujg/201103/201103170000033607.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').html('hello world'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').css({ 'fontSize': '100px', 'color': 'red'}); // setting multiple properties &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').height('50px');&amp;nbsp; // sets the height of all H1 elements &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').height();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // gets the height of the first H1 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('a').attr({&lt;br /&gt;&amp;nbsp;&amp;nbsp; 'title' : 'all titles are the same too!',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'href' : 'somethingNew.html'&lt;br /&gt;}); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').next('p'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('div:visible').parent(); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('input[name=first_name]').closest('form'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('#myList').children(); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('li.selected').siblings(); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('#myList li:first').clone().appendTo('#myList'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;var $myNewElement = $('&amp;lt;p&amp;gt;New element&amp;lt;/p&amp;gt;');&lt;br /&gt;$myNewElement.appendTo('#content'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').remove(); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('#myDiv').data('keyName', { foo : 'bar' });&lt;br /&gt;$('#myDiv').data('keyName'); // { foo : 'bar' } &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('p').click(function() {&lt;br /&gt;　　 console.log('click');&lt;br /&gt;}); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('p').bind('click', function() {&lt;br /&gt;　　 console.log('click');&lt;br /&gt;}); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('p').unbind('click'); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').show(); &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').fadeOut('slow');&amp;nbsp; // using a built-in speed definition &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-family: 宋体; font-size: 12pt;"&gt;$('h1').fadeIn(300);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // fade in over 300ms &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
﻿&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1987008.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1987008.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1918820.html</id><title type="text">.NET 性能优化方法总结</title><summary type="text">1. C#语言方面1.1 垃圾回收　垃圾回收解放了手工管理对象的工作，提高了程序的健壮性，但副作用就是程序代码可能对于对象创建变得随意。　1.1.1 避免不必要的对象创建　由于垃圾回收的代价较高，所以C#程序开发要遵循的一个基本原则就是避免不必要的对象创建。以下列举一些常见的情形。　1.1.1.1 避免循环创建对象 ★　如果对象并不会随每次循环而改变状态，那么在循环中反复创建对象将带来性能损耗。高效的做法是将对象提到循环外面创建。　1.1.1.2 在需要逻辑分支中创建对象　如果对象只在某些逻辑分支中才被用到，那么应只在该逻辑分支中创建对象。　1.1.1.3 使用常量避免创建对象　程序中不应出现</summary><published>2010-12-28T05:24:00Z</published><updated>2010-12-28T05:24:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1918820.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1918820.html"/><content type="html">&lt;p&gt;&lt;strong&gt;1. C#语言方面&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.1 垃圾回收&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;垃圾回收解放了手工管理对象的工作，提高了程序的健壮性，但副作用就是程序代码可能对于对象创建变得随意。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.1 避免不必要的对象创建&lt;/p&gt;&#xD;
&lt;p&gt;由于垃圾回收的代价较高，所以C#程序开发要遵循的一个基本原则就是避免不必要的对象创建。以下列举一些常见的情形。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.1.1 避免循环创建对象 ★&lt;/p&gt;&#xD;
&lt;p&gt;如果对象并不会随每次循环而改变状态，那么在循环中反复创建对象将带来性能损耗。高效的做法是将对象提到循环外面创建。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.1.2 在需要逻辑分支中创建对象&lt;/p&gt;&#xD;
&lt;p&gt;如果对象只在某些逻辑分支中才被用到，那么应只在该逻辑分支中创建对象。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.1.3 使用常量避免创建对象&lt;/p&gt;&#xD;
&lt;p&gt;程序中不应出现如 new Decimal(0) 之类的代码，这会导致小对象频繁创建及回收，正确的做法是使用Decimal.Zero常量。我们有设计自己的类时，也可以学习这个设计手法，应用到类似的场景中。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.1.4 使用StringBuilder做字符串连接&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.1.2 不要使用空析构函数 ★&lt;/p&gt;&#xD;
&lt;p&gt;如果类包含析构函数，由创建对象时会在 Finalize 队列中添加对象的引用，以保证当对象无法可达时，仍然可以调用到 Finalize 方法。垃圾回收器在运行期间，会启动一个低优先级的线程处理该队列。相比之下，没有析构函数的对象就没有这些消耗。如果析构函数为空，这个消耗就毫无意义，只会导致性能降低！因此，不要使用空的析构函数。&lt;/p&gt;&#xD;
&lt;p&gt;在实际情况中，许多曾在析构函数中包含处理代码，但后来因为种种原因被注释掉或者删除掉了，只留下一个空壳，此时应注意把析构函数本身注释掉或删除掉。&lt;/p&gt;&#xD;
&lt;p&gt;1.1.3 实现 IDisposable 接口&lt;/p&gt;&#xD;
&lt;p&gt;垃圾回收事实上只支持托管内在的回收，对于其他的非托管资源，例如 Window GDI 句柄或数据库连接，在析构函数中释放这些资源有很大问题。原因是垃圾回收依赖于内在紧张的情况，虽然数据库连接可能已濒临耗尽，但如果内存还很充足的话，垃圾回收是不会运行的。&lt;/p&gt;&#xD;
&lt;p&gt;C#的 IDisposable 接口是一种显式释放资源的机制。通过提供 using 语句，还简化了使用方式（编译器自动生成 try ... finally 块，并在 finally 块中调用 Dispose 方法）。对于申请非托管资源对象，应为其实现 IDisposable 接口，以保证资源一旦超出 using 语句范围，即得到及时释放。这对于构造健壮且性能优良的程序非常有意义！&lt;/p&gt;&#xD;
&lt;p&gt;为防止对象的 Dispose 方法不被调用的情况发生，一般还要提供析构函数，两者调用一个处理资源释放的公共方法。同时，Dispose 方法应调用 System.GC.SuppressFinalize(this)，告诉垃圾回收器无需再处理 Finalize 方法了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.2 String 操作&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.2.1 使用 StringBuilder 做字符串连接&lt;/p&gt;&#xD;
&lt;p&gt;String 是不变类，使用 + 操作连接字符串将会导致创建一个新的字符串。如果字符串连接次数不是固定的，例如在一个循环中，则应该使用 StringBuilder 类来做字符串连接工作。因为 StringBuilder 内部有一个 StringBuffer ，连接操作不会每次分配新的字符串空间。只有当连接后的字符串超出 Buffer 大小时，才会申请新的 Buffer 空间。典型代码如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;StringBuilder sb = new StringBuilder( 256 );&lt;/p&gt;&#xD;
&lt;p&gt;for ( int i = 0 ; i &amp;lt; Results.Count; i ++ )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;sb.Append (Results[i]);&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;如果连接次数是固定的并且只有几次，此时应该直接用 + 号连接，保持程序简洁易读。实际上，编译器已经做了优化，会依据加号次数调用不同参数个数的 String.Concat 方法。例如：String str = str1 + str2 + str3 + str4;&lt;/p&gt;&#xD;
&lt;p&gt;会被编译为 String.Concat(str1, str2, str3, str4)。该方法内部会计算总的 String 长度，仅分配一次，并不会如通常想象的那样分配三次。作为一个经验值，当字符串连接操作达到 10 次以上时，则应该使用 StringBuilder。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这里有一个细节应注意：StringBuilder 内部 Buffer 的缺省值为 16 ，这个值实在太小。按 StringBuilder 的使用场景，Buffer 肯定得重新分配。经验值一般用 256 作为 Buffer 的初值。当然，如果能计算出最终生成字符串长度的话，则应该按这个值来设定 Buffer 的初值。使用 new StringBuilder(256) 就将 Buffer 的初始长度设为了256。&lt;/p&gt;&#xD;
&lt;p&gt;1.2.2 避免不必要的调用 ToUpper 或 ToLower 方法&lt;/p&gt;&#xD;
&lt;p&gt;String是不变类，调用ToUpper或ToLower方法都会导致创建一个新的字符串。如果被频繁调用，将导致频繁创建字符串对象。这违背了前面讲到的&amp;ldquo;避免频繁创建对象&amp;rdquo;这一基本原则。&lt;/p&gt;&#xD;
&lt;p&gt;例如，bool.Parse方法本身已经是忽略大小写的，调用时不要调用ToLower方法。&lt;/p&gt;&#xD;
&lt;p&gt;另一个非常普遍的场景是字符串比较。高效的做法是使用 Compare 方法，这个方法可以做大小写忽略的比较，并且不会创建新字符串。&lt;/p&gt;&#xD;
&lt;p&gt;例：&lt;/p&gt;&#xD;
&lt;p&gt;const string C_VALUE = "COMPARE";&lt;/p&gt;&#xD;
&lt;p&gt;if (String.Compare(sVariable, C_VALUE, true) == 0)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;Console.Write("SAME");&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;还有一种情况是使用 HashTable 的时候，有时候无法保证传递 key 的大小写是否符合预期，往往会把 key 强制转换到大写或小写方法。实际上 HashTable 有不同的构造形式，完全支持采用忽略大小写的 key: new HashTable(StringComparer.OrdinalIgnoreCase)。&lt;/p&gt;&#xD;
&lt;p&gt;1.2.3 最快的空串比较方法&lt;/p&gt;&#xD;
&lt;p&gt;将String对象的Length属性与0比较是最快的方法：if (str.Length == 0)&lt;/p&gt;&#xD;
&lt;p&gt;其次是与String.Empty常量或空串比较：if (str == String.Empty)或if (str == "")&lt;/p&gt;&#xD;
&lt;p&gt;注：C#在编译时会将程序集中声明的所有字符串常量放到保留池中（intern pool），相同常量不会重复分配。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.3 多线程&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.3.1 线程同步&lt;/p&gt;&#xD;
&lt;p&gt;线程同步是编写多线程程序需要首先考虑问题。C#为同步提供了 Monitor、Mutex、AutoResetEvent 和 ManualResetEvent 对象来分别包装 Win32 的临界区、互斥对象和事件对象这几种基础的同步机制。C#还提供了一个lock语句，方便使用，编译器会自动生成适当的 Monitor.Enter 和 Monitor.Exit 调用。&lt;/p&gt;&#xD;
&lt;p&gt;1.3.1.1 同步粒度&lt;/p&gt;&#xD;
&lt;p&gt;同步粒度可以是整个方法，也可以是方法中某一段代码。为方法指定 MethodImplOptions.Synchronized 属性将标记对整个方法同步。例如：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;[MethodImpl(MethodImplOptions.Synchronized)]&lt;/p&gt;&#xD;
&lt;p&gt;public static SerialManager GetInstance()&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;if (instance == null )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;instance = new SerialManager();&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;return instance;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;通常情况下，应减小同步的范围，使系统获得更好的性能。简单将整个方法标记为同步不是一个好主意，除非能确定方法中的每个代码都需要受同步保护。&lt;/p&gt;&#xD;
&lt;p&gt;1.3.1.2 同步策略&lt;/p&gt;&#xD;
&lt;p&gt;使用 lock 进行同步，同步对象可以选择 Type、this 或为同步目的专门构造的成员变量。&lt;/p&gt;&#xD;
&lt;p&gt;避免锁定Type★ &lt;/p&gt;&#xD;
&lt;p&gt;锁定Type对象会影响同一进程中所有AppDomain该类型的所有实例，这不仅可能导致严重的性能问题，还可能导致一些无法预期的行为。这是一个很不好的习惯。即便对于一个只包含static方法的类型，也应额外构造一个static的成员变量，让此成员变量作为锁定对象。&lt;/p&gt;&#xD;
&lt;p&gt;避免锁定 this&lt;/p&gt;&#xD;
&lt;p&gt;锁定 this 会影响该实例的所有方法。假设对象 obj 有 A 和 B 两个方法，其中 A 方法使用 lock(this) 对方法中的某段代码设置同步保护。现在，因为某种原因，B 方法也开始使用 lock(this) 来设置同步保护了，并且可能为了完全不同的目的。这样，A 方法就被干扰了，其行为可能无法预知。所以，作为一种良好的习惯，建议避免使用 lock(this) 这种方式。&lt;/p&gt;&#xD;
&lt;p&gt;使用为同步目的专门构造的成员变量&lt;/p&gt;&#xD;
&lt;p&gt;这是推荐的做法。方式就是 new 一个 object 对象， 该对象仅仅用于同步目的。&lt;/p&gt;&#xD;
&lt;p&gt;如果有多个方法都需要同步，并且有不同的目的，那么就可以为些分别建立几个同步成员变量。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.3.1.4 集合同步&lt;/p&gt;&#xD;
&lt;p&gt;C#为各种集合类型提供了两种方便的同步机制：Synchronized 包装器和 SyncRoot 属性。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;// Creates and initializes a new ArrayList &lt;/p&gt;&#xD;
&lt;p&gt;ArrayList myAL = new ArrayList();&lt;/p&gt;&#xD;
&lt;p&gt;myAL.Add( " The " );&lt;/p&gt;&#xD;
&lt;p&gt;myAL.Add( " quick " );&lt;/p&gt;&#xD;
&lt;p&gt;myAL.Add( " brown " );&lt;/p&gt;&#xD;
&lt;p&gt;myAL.Add( " fox " );&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;// Creates a synchronized wrapper around the ArrayList &lt;/p&gt;&#xD;
&lt;p&gt;ArrayList mySyncdAL = ArrayList.Synchronized(myAL);&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;调用 Synchronized 方法会返回一个可保证所有操作都是线程安全的相同集合对象。考虑 mySyncdAL[0] = mySyncdAL[0] + "test" 这一语句，读和写一共要用到两个锁。一般讲，效率不高。推荐使用 SyncRoot 属性，可以做比较精细的控制。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.3.2 使用 ThreadStatic 替代 NameDataSlot ★&lt;/p&gt;&#xD;
&lt;p&gt;存取 NameDataSlot 的 Thread.GetData 和 Thread.SetData 方法需要线程同步，涉及两个锁：一个是 LocalDataStore.SetData 方法需要在 AppDomain 一级加锁，另一个是 ThreadNative.GetDomainLocalStore 方法需要在 Process 一级加锁。如果一些底层的基础服务使用了 NameDataSlot，将导致系统出现严重的伸缩性问题。&lt;/p&gt;&#xD;
&lt;p&gt;规避这个问题的方法是使用 ThreadStatic 变量。示例如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;public sealed class InvokeContext&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;[ThreadStatic]&lt;/p&gt;&#xD;
&lt;p&gt;private static InvokeContext current;&lt;/p&gt;&#xD;
&lt;p&gt;private Hashtable maps = new Hashtable();&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;1.3.3 多线程编程技巧&lt;/p&gt;&#xD;
&lt;p&gt;1.3.3.1 使用 Double Check 技术创建对象&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;internal IDictionary KeyTable&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;get &lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;if ( this ._keyTable == null )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;lock ( base ._lock)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;if ( this ._keyTable == null )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;this ._keyTable = new Hashtable();&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;return this ._keyTable;&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;创建单例对象是很常见的一种编程情况。一般在 lock 语句后就会直接创建对象了，但这不够安全。因为在 lock 锁定对象之前，可能已经有多个线程进入到了第一个 if 语句中。如果不加第二个 if 语句，则单例对象会被重复创建，新的实例替代掉旧的实例。如果单例对象中已有数据不允许被破坏或者别的什么原因，则应考虑使用 Double Check 技术。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.4 类型系统&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.4.1 避免无意义的变量初始化动作&lt;/p&gt;&#xD;
&lt;p&gt;CLR保证所有对象在访问前已初始化，其做法是将分配的内存清零。因此，不需要将变量重新初始化为0、false或null。&lt;/p&gt;&#xD;
&lt;p&gt;需要注意的是：方法中的局部变量不是从堆而是从栈上分配，所以C#不会做清零工作。如果使用了未赋值的局部变量，编译期间即会报警。不要因为有这个印象而对所有类的成员变量也做赋值动作，两者的机理完全不同！&lt;/p&gt;&#xD;
&lt;p&gt;1.4.2 ValueType 和 ReferenceType&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.4.2.1 以引用方式传递值类型参数&lt;/p&gt;&#xD;
&lt;p&gt;值类型从调用栈分配，引用类型从托管堆分配。当值类型用作方法参数时，默认会进行参数值复制，这抵消了值类型分配效率上的优势。作为一项基本技巧，以引用方式传递值类型参数可以提高性能。&lt;/p&gt;&#xD;
&lt;p&gt;1.4.2.2 为 ValueType 提供 Equals 方法&lt;/p&gt;&#xD;
&lt;p&gt;.net 默认实现的 ValueType.Equals 方法使用了反射技术，依靠反射来获得所有成员变量值做比较，这个效率极低。如果我们编写的值对象其 Equals 方法要被用到（例如将值对象放到 HashTable 中），那么就应该重载 Equals 方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;public struct Rectangle&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;public double Length;&lt;/p&gt;&#xD;
&lt;p&gt;public double Breadth;&lt;/p&gt;&#xD;
&lt;p&gt;public override bool Equals ( object ob)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;if (ob is Rectangle)&lt;/p&gt;&#xD;
&lt;p&gt;return Equels ((Rectangle)ob))&lt;/p&gt;&#xD;
&lt;p&gt;else &lt;/p&gt;&#xD;
&lt;p&gt;return false ;&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;private bool Equals (Rectangle rect)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;return this .Length == rect.Length &amp;amp;&amp;amp; this .Breadth == rect.Breach;&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;1.4.2.3 避免装箱和拆箱&lt;/p&gt;&#xD;
&lt;p&gt;C#可以在值类型和引用类型之间自动转换，方法是装箱和拆箱。装箱需要从堆上分配对象并拷贝值，有一定性能消耗。如果这一过程发生在循环中或是作为底层方法被频繁调用，则应该警惕累计的效应。&lt;/p&gt;&#xD;
&lt;p&gt;一种经常的情形出现在使用集合类型时。例如：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;ArrayList al = new ArrayList();&lt;/p&gt;&#xD;
&lt;p&gt;for ( int i = 0 ; i &amp;lt; 1000 ; i ++ )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;al.Add(i); // Implicitly boxed because Add() takes an object &lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;int f = ( int )al[ 0 ]; // The element is unboxed&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;但是得当心！如果你像使用引用类型那么频繁的使用一个值类型的话，值类型的优势会很快被耗尽。比如，把一个值类型压到一个含有对象类型的群集。这叫做装箱，很耗用处理器周期，尤其是当你的代码在把它作为值（对它进行数学运算）和把它作为引用之间来回运行时。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.4.3 尽可能使用最合适的类型&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;bull; 尽可能使用最合适的类型来描述数据，从而减少类型转换。 &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;bull; 使用泛型来创建群集和其它的数据结构，这样，在运行时，它们就可以被实例化来存储刚好合适的类型。这节省了装箱/拆箱和类型转换的时间。 &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;bull; 在C#中使用as,而不是is。关键字is用来查看引用是否可以被作为某个具体的类型，但是并不返回转换到这个类型的引用。所以，通常当你从is获得一个正的结果时，你首先应该cast&amp;mdash;&amp;mdash;有效地执行两次cast。采用as关键词时，如果可用，则返回cast为新类型的引用；否则返回null。你可以查看null然后做你喜欢做的事情。整体来说，As方法要比is方法快50%。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.5 异常处理&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;异常也是现代语言的典型特征。与传统检查错误码的方式相比，异常是强制性的（不依赖于是否忘记了编写检查错误码的代码）、强类型的、并带有丰富的异常信息（例如调用栈）。&lt;/p&gt;&#xD;
&lt;p&gt;1.5.1 不要吃掉异常★&lt;/p&gt;&#xD;
&lt;p&gt;关于异常处理的最重要原则就是：不要吃掉异常。这个问题与性能无关，但对于编写健壮和易于排错的程序非常重要。这个原则换一种说法，就是不要捕获那些你不能处理的异常。&lt;/p&gt;&#xD;
&lt;p&gt;吃掉异常是极不好的习惯，因为你消除了解决问题的线索。一旦出现错误，定位问题将非常困难。除了这种完全吃掉异常的方式外，只将异常信息写入日志文件但并不做更多处理的做法也同样不妥。&lt;/p&gt;&#xD;
&lt;p&gt;1.5.2 不要吃掉异常信息★&lt;/p&gt;&#xD;
&lt;p&gt;有些代码虽然抛出了异常，但却把异常信息吃掉了。&lt;/p&gt;&#xD;
&lt;p&gt;为异常披露详尽的信息是程序员的职责所在。如果不能在保留原始异常信息含义的前提下附加更丰富和更人性化的内容，那么让原始的异常信息直接展示也要强得多。千万不要吃掉异常。&lt;/p&gt;&#xD;
&lt;p&gt;1.5.3 避免不必要的抛出异常&lt;/p&gt;&#xD;
&lt;p&gt;抛出异常和捕获异常属于消耗比较大的操作，在可能的情况下，应通过完善程序逻辑避免抛出不必要不必要的异常。与此相关的一个倾向是利用异常来控制处理逻辑。尽管对于极少数的情况，这可能获得更为优雅的解决方案，但通常而言应该避免。&lt;/p&gt;&#xD;
&lt;p&gt;1.5.4 避免不必要的重新抛出异常&lt;/p&gt;&#xD;
&lt;p&gt;如果是为了包装异常的目的（即加入更多信息后包装成新异常），那么是合理的。但是有不少代码，捕获异常没有做任何处理就再次抛出，这将无谓地增加一次捕获异常和抛出异常的消耗，对性能有伤害。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.5.5 捕获指定的异常，不要使用通用的System.Exception.　　&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//避免&lt;/p&gt;&#xD;
&lt;p&gt;try&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;catch(Exception exc)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;//推荐&lt;/p&gt;&#xD;
&lt;p&gt;try&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;catch(System.NullReferenceException exc)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;catch(System.ArgumentOutOfRangeException exc)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;catch(System.InvalidCastException exc)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.5.6 要在finally里释放占用的资源&lt;/p&gt;&#xD;
&lt;p&gt;使用Try...catch...finally时， 要在finally里释放占用的资源如连接，文件流等，不然在Catch到错误后占用的资源不能释放。&lt;/p&gt;&#xD;
&lt;p&gt;try&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;...&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;catch&lt;/p&gt;&#xD;
&lt;p&gt;{...}&lt;/p&gt;&#xD;
&lt;p&gt;finally&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;conntion.close()&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.6 反射&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;反射是一项很基础的技术，它将编译期间的静态绑定转换为延迟到运行期间的动态绑定。在很多场景下（特别是类框架的设计），可以获得灵活易于扩展的架构。但带来的问题是与静态绑定相比，动态绑定会对性能造成较大的伤害。&lt;/p&gt;&#xD;
&lt;p&gt;1.6.1 反射分类&lt;/p&gt;&#xD;
&lt;p&gt;type comparison ：类型判断，主要包括 is 和 typeof 两个操作符及对象实例上的 GetType 调用。这是最轻型的消耗，可以无需考虑优化问题。注意 typeof 运算符比对象实例上的 GetType 方法要快，只要可能则优先使用 typeof 运算符。&lt;/p&gt;&#xD;
&lt;p&gt;member enumeration ： 成员枚举，用于访问反射相关的元数据信息，例如Assembly.GetModule、Module.GetType、Type对象上的IsInterface、IsPublic、GetMethod、GetMethods、GetProperty、GetProperties、GetConstructor调用等。尽管元数据都会被CLR缓存，但部分方法的调用消耗仍非常大，不过这类方法调用频度不会很高，所以总体看性能损失程度中等。&lt;/p&gt;&#xD;
&lt;p&gt;member invocation：成员调用，包括动态创建对象及动态调用对象方法，主要有Activator.CreateInstance、Type.InvokeMember等。&lt;/p&gt;&#xD;
&lt;p&gt;1.6.2 动态创建对象&lt;/p&gt;&#xD;
&lt;p&gt;C#主要支持 5 种动态创建对象的方式：&lt;/p&gt;&#xD;
&lt;p&gt;1. Type.InvokeMember&lt;/p&gt;&#xD;
&lt;p&gt;2. ContructorInfo.Invoke&lt;/p&gt;&#xD;
&lt;p&gt;3. Activator.CreateInstance(Type)&lt;/p&gt;&#xD;
&lt;p&gt;4. Activator.CreateInstance(assemblyName, typeName)&lt;/p&gt;&#xD;
&lt;p&gt;5. Assembly.CreateInstance(typeName)&lt;/p&gt;&#xD;
&lt;p&gt;最快的是方式 3 ，与 Direct Create 的差异在一个数量级之内，约慢 7 倍的水平。其他方式，至少在 40 倍以上，最慢的是方式 4 ，要慢三个数量级。&lt;/p&gt;&#xD;
&lt;p&gt;1.6.3 动态方法调用&lt;/p&gt;&#xD;
&lt;p&gt;方法调用分为编译期的早期绑定和运行期的动态绑定两种，称为Early-Bound Invocation和Late-Bound Invocation。Early-Bound Invocation可细分为Direct-call、Interface-call和Delegate-call。Late-Bound Invocation主要有Type.InvokeMember和MethodBase.Invoke，还可以通过使用LCG（Lightweight Code Generation）技术生成IL代码来实现动态调用。&lt;/p&gt;&#xD;
&lt;p&gt;从测试结果看，相比Direct Call，Type.InvokeMember要接近慢三个数量级；MethodBase.Invoke虽然比Type.InvokeMember要快三倍，但比Direct Call仍慢270倍左右。可见动态方法调用的性能是非常低下的。我们的建议是：除非要满足特定的需求，否则不要使用！&lt;/p&gt;&#xD;
&lt;p&gt;1.6.4 推荐的使用原则&lt;/p&gt;&#xD;
&lt;p&gt;模式&lt;/p&gt;&#xD;
&lt;p&gt;1． 如果可能，则避免使用反射和动态绑定&lt;/p&gt;&#xD;
&lt;p&gt;2． 使用接口调用方式将动态绑定改造为早期绑定&lt;/p&gt;&#xD;
&lt;p&gt;3． 使用Activator.CreateInstance(Type)方式动态创建对象&lt;/p&gt;&#xD;
&lt;p&gt;4． 使用typeof操作符代替GetType调用&lt;/p&gt;&#xD;
&lt;p&gt;反模式&lt;/p&gt;&#xD;
&lt;p&gt;1． 在已获得Type的情况下，却使用Assembly.CreateInstance(type.FullName)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.7 基本代码技巧&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这里描述一些应用场景下，可以提高性能的基本代码技巧。对处于关键路径的代码，进行这类的优化还是很有意义的。普通代码可以不做要求，但养成一种好的习惯也是有意义的。&lt;/p&gt;&#xD;
&lt;p&gt;1.7.1 循环写法&lt;/p&gt;&#xD;
&lt;p&gt;可以把循环的判断条件用局部变量记录下来。局部变量往往被编译器优化为直接使用寄存器，相对于普通从堆或栈中分配的变量速度快。如果访问的是复杂计算属性的话，提升效果将更明显。for (int i = 0, j = collection.GetIndexOf(item); i &amp;lt; j; i++)&lt;/p&gt;&#xD;
&lt;p&gt;需要说明的是：这种写法对于CLR集合类的Count属性没有意义，原因是编译器已经按这种方式做了特别的优化。&lt;/p&gt;&#xD;
&lt;p&gt;1.7.2 拼装字符串&lt;/p&gt;&#xD;
&lt;p&gt;拼装好之后再删除是很低效的写法。有些方法其循环长度在大部分情况下为1，这种写法的低效就更为明显了：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;public static string ToString(MetadataKey entityKey)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;string str = "" ;&lt;/p&gt;&#xD;
&lt;p&gt;object [] vals = entityKey.values;&lt;/p&gt;&#xD;
&lt;p&gt;for ( int i = 0 ; i &amp;lt; vals.Length; i ++ )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;str += " , " + vals[i].ToString();&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;return str == "" ? "" : str.Remove( 0 , 1 );&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;推荐下面的写法：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;if (str.Length == 0 )&lt;/p&gt;&#xD;
&lt;p&gt;str = vals[i].ToString();&lt;/p&gt;&#xD;
&lt;p&gt;else &lt;/p&gt;&#xD;
&lt;p&gt;str += " , " + vals[i].ToString();&lt;/p&gt;&#xD;
&lt;p&gt;其实这种写法非常自然，而且效率很高，完全不需要用个Remove方法绕来绕去。&lt;/p&gt;&#xD;
&lt;p&gt;1.7.3 避免两次检索集合元素&lt;/p&gt;&#xD;
&lt;p&gt;获取集合元素时，有时需要检查元素是否存在。通常的做法是先调用ContainsKey（或Contains）方法，然后再获取集合元素。这种写法非常符合逻辑。 &lt;/p&gt;&#xD;
&lt;p&gt;但如果考虑效率，可以先直接获取对象，然后判断对象是否为null来确定元素是否存在。对于Hashtable，这可以节省一次GetHashCode调用和n次Equals比较。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如下面的示例：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;public IData GetItemByID(Guid id)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;IData data1 = null ;&lt;/p&gt;&#xD;
&lt;p&gt;if ( this .idTable.ContainsKey(id.ToString())&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;data1 = this .idTable[id.ToString()] as IData;&lt;/p&gt;&#xD;
&lt;p&gt;} &lt;/p&gt;&#xD;
&lt;p&gt;return data1;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;其实完全可用一行代码完成：return this.idTable[id] as IData;&lt;/p&gt;&#xD;
&lt;p&gt;1.7.4 避免两次类型转换&lt;/p&gt;&#xD;
&lt;p&gt;考虑如下示例，其中包含了两处类型转换：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;if (obj is SomeType)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;SomeType st = (SomeType)obj;&lt;/p&gt;&#xD;
&lt;p&gt;st.SomeTypeMethod();&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;效率更高的做法如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;SomeType st = obj as SomeType;&lt;/p&gt;&#xD;
&lt;p&gt;if (st != null )&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;st.SomeTypeMethod();&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.7.5为字符串容器声明常量，不要直接把字符封装在双引号" "里面。&lt;/p&gt;&#xD;
&lt;p&gt;//避免&lt;/p&gt;&#xD;
&lt;p&gt;//&lt;/p&gt;&#xD;
&lt;p&gt;MyObject obj = new MyObject();&lt;/p&gt;&#xD;
&lt;p&gt;obj.Status = "ACTIVE";&lt;/p&gt;&#xD;
&lt;p&gt;//推荐&lt;/p&gt;&#xD;
&lt;p&gt;const string C_STATUS = "ACTIVE";&lt;/p&gt;&#xD;
&lt;p&gt;MyObject obj = new MyObject();&lt;/p&gt;&#xD;
&lt;p&gt;obj.Status = C_STATUS;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.7.6 用StringBuilder代替使用字符串连接符 &amp;ldquo;+&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//避免&lt;/p&gt;&#xD;
&lt;p&gt;String sXML = " ";&lt;/p&gt;&#xD;
&lt;p&gt;sXML += "";&lt;/p&gt;&#xD;
&lt;p&gt;sXML += "Data";&lt;/p&gt;&#xD;
&lt;p&gt;sXML += "";&lt;/p&gt;&#xD;
&lt;p&gt;sXML += "";&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//推荐&lt;/p&gt;&#xD;
&lt;p&gt;StringBuilder sbXML = new StringBuilder();&lt;/p&gt;&#xD;
&lt;p&gt;sbXML.Append(" ");&lt;/p&gt;&#xD;
&lt;p&gt;sbXML.Append("");&lt;/p&gt;&#xD;
&lt;p&gt;sbXML.Append("Data");&lt;/p&gt;&#xD;
&lt;p&gt;sbXML.Append("");&lt;/p&gt;&#xD;
&lt;p&gt;sbXML.Append("");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.7.7 避免在循环体里声明变量，&lt;/p&gt;&#xD;
&lt;p&gt;应该在循环体外声明变量，在循环体里初始化。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//避免&lt;/p&gt;&#xD;
&lt;p&gt;for(int i=0; i&amp;lt;10; i++)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;SomeClass objSC = new SomeClass();&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//推荐&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;SomeClass objSC = null;&lt;/p&gt;&#xD;
&lt;p&gt;for(int i=0; i&amp;lt;10; i++)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;objSC = new SomeClass();&lt;/p&gt;&#xD;
&lt;p&gt;)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.8 Hashtable&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.8.1 Hashtable机理　&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Hashtable是一种使用非常频繁的基础集合类型。需要理解影响Hashtable的效率有两个因素：一是散列码（GetHashCode方法），二是等值比较（Equals方法）。Hashtable首先使用键的散列码将对象分布到不同的存储桶中，随后在该特定的存储桶中使用键的Equals方法进行查找。&lt;/p&gt;&#xD;
&lt;p&gt;良好的散列码是第一位的因素，最理想的情况是每个不同的键都有不同的散列码。Equals方法也很重要，因为散列只需要做一次，而存储桶中查找键可能需要做多次。从实际经验看，使用Hashtable时，Equals方法的消耗一般会占到一半以上。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;System.Object类提供了默认的GetHashCode实现，使用对象在内存中的地址作为散列码。我们遇到过一个用Hashtable来缓存对象的例子，每次根据传递的OQL表达式构造出一个ExpressionList对象，再调用QueryCompiler的方法编译得到CompiledQuery对象。以ExpressionList对象和CompiledQuery对象作为键值对存储到Hashtable中。ExpressionList对象没有重载GetHashCode实现，其超类ArrayList也没有，这样最后用的就是System.Object类的GetHashCode实现。由于ExpressionList对象会每次构造，因此它的HashCode每次都不同，所以这个CompiledQueryCache根本就没有起到预想的作用。这个小小的疏漏带来了重大的性能问题，由于解析OQL表达式频繁发生，导致CompiledQueryCache不断增长，造成服务器内存泄漏！解决这个问题的最简单方法就是提供一个常量实现，例如让散列码为常量0。虽然这会导致所有对象汇聚到同一个存储桶中，效率不高，但至少可以解决掉内存泄漏问题。当然，最终还是会实现一个高效的GetHashCode方法的。&lt;/p&gt;&#xD;
&lt;p&gt;以上介绍这些Hashtable机理，主要是希望大家理解：如果使用Hashtable，你应该检查一下对象是否提供了适当的GetHashCode和Equals方法实现。否则，有可能出现效率不高或者与预期行为不符的情况。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.8.2&amp;nbsp; 使用HashTale代替其他字典集合类型的情形&lt;/strong&gt;：&lt;/p&gt;&#xD;
&lt;p&gt;其他字典集合类型(如StringDictionary,NameValueCollection,HybridCollection)，存放少量数据的时候可以使用HashTable　。&lt;/p&gt;&#xD;
&lt;p&gt;很多非泛型集合类都有对应的泛型集合类，下面是常用的非泛型集合类以及对应的泛型集合类：&lt;/p&gt;&#xD;
&lt;p&gt;非泛型集合类 泛型集合类 &lt;/p&gt;&#xD;
&lt;p&gt;ArrayList List&amp;lt;T&amp;gt; &lt;/p&gt;&#xD;
&lt;p&gt;HashTable DIctionary&amp;lt;T&amp;gt; &lt;/p&gt;&#xD;
&lt;p&gt;Queue Queue&amp;lt;T&amp;gt; &lt;/p&gt;&#xD;
&lt;p&gt;Stack Stack&amp;lt;T&amp;gt; &lt;/p&gt;&#xD;
&lt;p&gt;SortedList SortedList&amp;lt;T&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我们用的比较多的非泛型集合类主要有 ArrayList类 和 HashTable类。我们经常用HashTable 来存储将要写入到数据库或者返回的信息，在这之间要不断的进行类型的转化，增加了系统装箱和拆箱的负担，如果我们操纵的数据类型相对确定的化&amp;nbsp; 用 Dictionary&amp;lt;TKey,TValue&amp;gt; 集合类来存储数据就方便多了，例如我们需要在电子商务网站中存储用户的购物车信息( 商品名，对应的商品个数)时，完全可以用 Dictionary&amp;lt;string, int&amp;gt; 来存储购物车信息，而不需要任何的类型转化。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.9&amp;nbsp; 避免使用ArrayList。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;因为任何对象添加到ArrayList都要封箱为System.Object类型，从ArrayList取出数据时，要拆箱回实际的类型。建议使用自定义的集合类型代替ArrayList。.net 2.0提供了一个新的类型，叫泛型，这是一个强类型，使用泛型集合就可以避免了封箱和拆箱的发生，提高了性能。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1.10从XML对象读取数据&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果只是从XML对象读取数据，用只读的XPathDocument代替XMLDocument,可以提高性能&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;//避免&lt;/p&gt;&#xD;
&lt;p&gt;XmlDocument xmld = new XmlDocument();&lt;/p&gt;&#xD;
&lt;p&gt;xmld.LoadXml(sXML);&lt;/p&gt;&#xD;
&lt;p&gt;txtName.Text = xmld.SelectSingleNode("/packet/child").InnerText;&lt;/p&gt;&#xD;
&lt;p&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;//推荐&lt;/p&gt;&#xD;
&lt;p&gt;XPathDocument xmldContext = new XPathDocument(new StringReader(oContext.Value));&lt;/p&gt;&#xD;
&lt;p&gt;XPathNavigator xnav = xmldContext.CreateNavigator();&lt;/p&gt;&#xD;
&lt;p&gt;XPathNodeIterator xpNodeIter = xnav.Select("packet/child");&lt;/p&gt;&#xD;
&lt;p&gt;iCount = xpNodeIter.Count;&lt;/p&gt;&#xD;
&lt;p&gt;xpNodeIter = xnav.SelectDescendants(XPathNodeType.Element, false);&lt;/p&gt;&#xD;
&lt;p&gt;while(xpNodeIter.MoveNext())&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;sCurrValues += xpNodeIter.Current.Value+"~";&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;　1.11 避免使用递归调用和嵌套循环，&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用他们会严重影响性能，在不得不用的时候才使用。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;　1.12 使用适当的Caching策略来提高性能&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;　2. Ado.Net&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2.1 应用Ado.net的一些思考原则&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 根据数据使用的方式来设计数据访问层&lt;/p&gt;&#xD;
&lt;p&gt;2. 缓存数据，避免不必要的操作&lt;/p&gt;&#xD;
&lt;p&gt;3. 使用服务帐户进行连接&lt;/p&gt;&#xD;
&lt;p&gt;4. 必要时申请，尽早释放&lt;/p&gt;&#xD;
&lt;p&gt;5. 关闭可关闭的资源&lt;/p&gt;&#xD;
&lt;p&gt;6. 减少往返&lt;/p&gt;&#xD;
&lt;p&gt;7. 仅返回需要的数据&lt;/p&gt;&#xD;
&lt;p&gt;8. 选择适当的事务类型&lt;/p&gt;&#xD;
&lt;p&gt;9. 使用存储过程&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2.2 Connection&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;数据库连接是一种共享资源，并且打开和关闭的开销较大。Ado.net默认启用了连接池机制，关闭连接不会真的关闭物理连接，而只是把连接放回到连接池中。因为池中共享的连接资源始终是有限的，如果在使用连接后不尽快关闭连接，那么就有可能导致申请连接的线程被阻塞住，影响整个系统的性能表现。&lt;/p&gt;&#xD;
&lt;p&gt;2.2.1 在方法中打开和关闭连接&lt;/p&gt;&#xD;
&lt;p&gt;这个原则有几层含义：&lt;/p&gt;&#xD;
&lt;p&gt;1. 主要目的是为了做到必要时申请和尽早释放&lt;/p&gt;&#xD;
&lt;p&gt;2. 不要在类的构造函数中打开连接、在析构函数中释放连接。因为这将依赖于垃圾回收，而垃圾回收只受内存影响，回收时机不定&lt;/p&gt;&#xD;
&lt;p&gt;3. 不要在方法之间传递连接，这往往导致连接保持打开的时间过长&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这里强调一下在方法之间传递连接的危害：曾经在压力测试中遇到过一个测试案例，当增大用户数的时候，这个案例要比别的案例早很久就用掉连接池中的所有连接。经分析，就是因为A方法把一个打开的连接传递到了B方法，而B方法又调用了一个自行打开和关闭连接的C方法。在A方法的整个运行期间，它至少需要占用两条连接才能够成功工作，并且其中的一条连接占用时间还特别长，所以造成连接池资源紧张，影响了整个系统的可伸缩性！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.2.2 显式关闭连接&lt;/p&gt;&#xD;
&lt;p&gt;Connection对象本身在垃圾回收时可以被关闭，而依赖垃圾回收是很不好的策略。推荐使用using语句显式关闭连接，如下例：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;using (SqlConnection conn = new SqlConnection(connString))&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;conn.Open();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;} // Dispose is automatically called on the conn variable here&lt;/p&gt;&#xD;
&lt;p&gt;2.2.3 确保连接池启用&lt;/p&gt;&#xD;
&lt;p&gt;Ado.net是为每个不同的连接串建立连接池，因此应该确保连接串不会出现与具体用户相关的信息。另外，要注意连接串是大小写敏感的。&lt;/p&gt;&#xD;
&lt;p&gt;2.2.4 不要缓存连接&lt;/p&gt;&#xD;
&lt;p&gt;例如，把连接缓存到Session或Application中。在启用连接池的情况下，这种做法没有任何意义。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;　2.3 Command&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.3.1 使用ExecuteScalar和ExecuteNonQuery&lt;/p&gt;&#xD;
&lt;p&gt;如果想返回像Count(*)、Sum(Price)或Avg(Quantity)那样的单值，可以使用ExecuteScalar方法。ExecuteScalar返回第一行第一列的值，将结果集作为标量值返回。因为单独一步就能完成，所以ExecuteScalar不仅简化了代码，还提高了性能。&lt;/p&gt;&#xD;
&lt;p&gt;使用不返回行的SQL语句时，例如修改数据（INSERT、UPDATE或DELETE）或仅返回输出参数或返回值，请使用ExecuteNonQuery。这避免了用于创建空DataReader的任何不必要处理。&lt;/p&gt;&#xD;
&lt;p&gt;2.3.2 使用Prepare&lt;/p&gt;&#xD;
&lt;p&gt;当需要重复执行同一SQL语句多次，可考虑使用Prepare方法提升效率。需要注意的是，如果只是执行一次或两次，则完全没有必要。例如：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.CommandText = "insert into Table1 ( Col1, Col2 ) values ( @val1, @val2 )";&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters.Add( "@val1", SqlDbType.Int, 4, "Col1" );&lt;/p&gt;&#xD;
&lt;p&gt;cms.Parameters.Add( "@val2", SqlDbType.NChar, 50, "Col2");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[0].Value = 1;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[1].Value = "XXX";&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Prepare();&lt;/p&gt;&#xD;
&lt;p&gt;cmd.ExecuteNonQuery();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[0].Value = 2;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[1].Value = "YYY";&lt;/p&gt;&#xD;
&lt;p&gt;cmd.ExecuteNonQuery();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[0].Value = 3;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.Parameters[1].Value = "ZZZ";&lt;/p&gt;&#xD;
&lt;p&gt;cmd.ExecuteNonQuery();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.3.3 使用绑定变量 ★&lt;/p&gt;&#xD;
&lt;p&gt;SQL语句需要先被编译成执行计划，然后再执行。如果使用绑定变量的方式，那么这个执行计划就可以被后续执行的SQL语句所复用。而如果直接把参数合并到了SQL语句中，由于参数值千变万化，执行计划就难以被复用了。例如上面Prepare一节给出的示例，如果把参数值直接写到insert语句中，那么上面的四次调用将需要编译四次执行计划。&lt;/p&gt;&#xD;
&lt;p&gt;为避免这种情况造成性能损失，要求一律使用绑定变量方式。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;　2.4 DataReader&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;DataReader最适合于访问只读的单向数据集。与DataSet不同，数据集并不全部在内存中，而是随不断发出的read请求，一旦发现数据缓冲区中的数据均被读取，则从数据源传输一个数据缓冲区大小的数据块过来。另外，DataReader保持连接，DataSet则与连接断开。&lt;/p&gt;&#xD;
&lt;p&gt;2.4.1 显式关闭DataReader&lt;/p&gt;&#xD;
&lt;p&gt;与连接类似，也需要显式关闭DataReader。另外，如果与DataReader关联的Connection仅为DataReader服务的话，可考虑使用Command对象的ExecuteReader(CommandBehavior.CloseConnection)方式。这可以保证当DataReader关闭时，同时自动关闭Connection。&lt;/p&gt;&#xD;
&lt;p&gt;2.4.2 用索引号访问代替名称索引号访问属性&lt;/p&gt;&#xD;
&lt;p&gt;从Row中访问某列属性，使用索引号的方式比使用名称方式有细微提高。如果会被频繁调用，例如在循环中，那么可考虑此类优化。示例如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.CommandText = "select Col1, Col2 from Table1" ;&lt;/p&gt;&#xD;
&lt;p&gt;SqlDataReader dr = cmd.ExecuteReader();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;int col1 = dr.GetOrdinal("Col1");&lt;/p&gt;&#xD;
&lt;p&gt;int col2 = dr.GetOrdinal("Col2");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;while (dr.Read())&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;Console.WriteLine( dr[col1] + "_" + dr[col2]);&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.4.3 使用类型化方法访问属性&lt;/p&gt;&#xD;
&lt;p&gt;从Row中访问某列属性，用GetString、GetInt32这种显式指明类型的方法，其效率较通用的GetValue方法有细微提高，因为不需要做类型转换。&lt;/p&gt;&#xD;
&lt;p&gt;2.4.4 使用多数据集&lt;/p&gt;&#xD;
&lt;p&gt;部分场景可以考虑一次返回多数据集来降低网络交互次数，提升效率。示例如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;cmd.CommandText = "StoredProcedureName"; // The stored procedure returns multiple result sets.&lt;/p&gt;&#xD;
&lt;p&gt;SqlDataReader dr = cmd.ExecuteReader();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;while (dr.read())&lt;/p&gt;&#xD;
&lt;p&gt;// read first result set&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;dr.NextResult();&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;while (dr.read())&lt;/p&gt;&#xD;
&lt;p&gt;//&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2.5 DataSet&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.5.1 利用索引加快查找行的效率&lt;/p&gt;&#xD;
&lt;p&gt;如果需要反复查找行，建议增加索引。有两种方式：&lt;/p&gt;&#xD;
&lt;p&gt;1. 设置DataTable的PrimaryKey&lt;/p&gt;&#xD;
&lt;p&gt;适用于按PrimaryKey查找行的情况。注意此时应调用DataTable.Rows.Find方法，一般惯用的Select方法不能利用索引。&lt;/p&gt;&#xD;
&lt;p&gt;2. 使用DataView&lt;/p&gt;&#xD;
&lt;p&gt;适用于按Non-PrimaryKey查找行的情况。可为DataTable创建一个DataView，并通过SortOrder参数指示建立索引。此后使用Find或FindRows查找行。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.ASP.NET&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.1 减少往返行程（Reduce Round Trips）&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用下面的方法可以减少Web服务器和Browser之间的往返行程：&lt;/p&gt;&#xD;
&lt;p&gt;1. 为Browser启用缓存&lt;/p&gt;&#xD;
&lt;p&gt;如果呈现的内容是静态的或变化周期较长，应启用Browser缓存，避免发出冗余的http请求。&lt;/p&gt;&#xD;
&lt;p&gt;2. 缓冲页面输出&lt;/p&gt;&#xD;
&lt;p&gt;如果可能，则尽量缓冲页面输出，处理结束后再一次传送到客户端，这可以避免频繁传递小块内容所造成的多次网络交互。由于这种方式在页面处理结束之前客户端无法看到页面内容，因此如果一个页面的尺寸较大的话，可考虑使用Response.Flush方法。该方法强制输出迄今为止在缓冲区中的内容，你应当采用合理的算法控制调用Response.Flush方法的次数。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 使用Server.Transfer重定向请求&lt;/p&gt;&#xD;
&lt;p&gt;使用Server.Transfer方法重定向请求优于Response.Redirect方法。原因是Response.Redirect会向Broswer回送一个响应头，在响应头中指出重定向的URL，之后Brower使用新的URL重新发出请求。而Server.Transfer方法直接是一个简单的服务端调用，完全没有这些开销！&lt;/p&gt;&#xD;
&lt;p&gt;需要注意Server.Transfer有局限性：第一，它会跳过安全检查；第二，只适用于在同一Web应用内的页面间跳转。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.2 避免阻塞和长时间的作业&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果需要运行阻塞或长时间运行的操作，可以考虑使用异步调用的机制，以便Web服务器能够继续处理其它的请求。&lt;/p&gt;&#xD;
&lt;p&gt;1. 使用异步方式调用Web服务和远程对象&lt;/p&gt;&#xD;
&lt;p&gt;只要有可能就要避免在请求的处理过程中对Web服务和远程对象的同步调用，因为它占用的是的ASP.NET 线程池中的工作线程，这将直接影响Web服务器响应其它请求的能力。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 考虑给不需要返回值的Web方法或远程对象的方法添加OneWay属性&lt;/p&gt;&#xD;
&lt;p&gt;这种模式能让Web Server调用之后就立即返回。可根据实际情况决定是否使用这种方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 使用工作队列&lt;/p&gt;&#xD;
&lt;p&gt;将作业提交到服务器上的工作队列中。客户端通过发送请求来轮询作业的执行结果。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.3 使用缓存&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;缓存能在很大程度上决定ASP.NET应用的最终性能。Asp.net支持页面输出缓存和页面部分缓存，并提供Cache API，供应用程序缓存自己的数据。是否使用缓存可考虑下面的要点：&lt;/p&gt;&#xD;
&lt;p&gt;1. 识别创建与访问代价较大的数据&lt;/p&gt;&#xD;
&lt;p&gt;2. 评估需要缓存数据的易变性&lt;/p&gt;&#xD;
&lt;p&gt;3. 评估数据的使用频次&lt;/p&gt;&#xD;
&lt;p&gt;4. 将要缓存数据中易变数据和不变数据分离，只缓存不变数据&lt;/p&gt;&#xD;
&lt;p&gt;5. 选择合适的缓存机制（除Asp.net Cache外，Application state和Session state也可以作为缓存使用）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.4 多线程&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 避免在请求处理过程中创建线程&lt;/p&gt;&#xD;
&lt;p&gt;在执行请求的过程中创建线程是一种代价较大的操作，会严重影响Web Server的性能。如果后续的操作必须用线程完成，建议通过thread pool来创建/管理线程。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 不要依赖线程数据槽或线程静态变量&lt;/p&gt;&#xD;
&lt;p&gt;由于执行请求的线程是ASP.NET thread pool中的工作线程，同一个Client的两次请求不一定由相同的线程来处理。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 避免阻塞处理请求的线程&lt;/p&gt;&#xD;
&lt;p&gt;参考"避免阻塞和长时间的作业"小节。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 避免异步调用&lt;/p&gt;&#xD;
&lt;p&gt;这和1的情况类似。异步调用会导致创建新的线程，增加服务器的负担。所以，如果没有并发的作业要执行，就不要执行异步调用。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.5 系统资源&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 考虑实现资源池以提升性能&lt;/p&gt;&#xD;
&lt;p&gt;2. 明确地调用Dispose或Close释放系统资源&lt;/p&gt;&#xD;
&lt;p&gt;3. 不要缓存或长时间占用资源池中的资源&lt;/p&gt;&#xD;
&lt;p&gt;4. 尽可能晚的申请，尽可能早的释放&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.6 页面处理&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽量减小Page的尺寸&lt;/p&gt;&#xD;
&lt;p&gt;包括缩短控件的名称、CSS的class的名称、去掉无谓空行和空格、禁用不需要的ViewState&lt;/p&gt;&#xD;
&lt;p&gt;2. 启用页面输出的缓冲区（Buffer）&lt;/p&gt;&#xD;
&lt;p&gt;如果Buffer的机制被关闭，可以用下面的方法打开。&lt;/p&gt;&#xD;
&lt;p&gt;使用程序打开页面输出缓存：&lt;/p&gt;&#xD;
&lt;p&gt;Response.BufferOutput = true;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用@Page开关打开页面输出缓冲机制：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;%@ Page Buffer = "true" %&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用Web.config或Machine.config配置文件的&amp;lt;pages&amp;gt;节点：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;pages buffer="true" &amp;hellip;&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 利用Page.IsPostBack优化页面输出&lt;/p&gt;&#xD;
&lt;p&gt;4. 通过分离页面的不同的内容，来提高缓存效率和减少呈现的时间 &lt;/p&gt;&#xD;
&lt;p&gt;5. 优化复杂和代价较大的循环 &lt;/p&gt;&#xD;
&lt;p&gt;6. 合理利用客户端的计算资源，将一些操作转移到客户端进行&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.7 ViewState&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;ViewState是Asp.net为服务端控件在页面回传之间跟踪状态信息而设计的一种机制。&lt;/p&gt;&#xD;
&lt;p&gt;1. 关闭ViewState&lt;/p&gt;&#xD;
&lt;p&gt;如果不需要跟踪页面状态，例如页面不会 回传（PostBack）、不需要处理服务端控件事件或者每次页面刷新时都会重新计算控件内容，那么就不需要用ViewState来记录页面状态了。可以对特定的WebControl设置EnableViewState属性，也可以在页面一级设置：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;%@ Page EnableViewState="false" %&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 在恰当的时间点初始化控件属性&lt;/p&gt;&#xD;
&lt;p&gt;ASP.NET的控件在执行构造函数、初始化的期间设置的属性不会被跟踪变化；而在初始化阶段之后对属性的修改都会被跟踪，并最终记录到IE页面的__VIEWSTATE之中。所以，选择合理的初始化控件属性的执行点，能有效的减小页面尺寸。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 谨慎选择放到ViewState中的内容&lt;/p&gt;&#xD;
&lt;p&gt;放到ViewState中的内容会被序列化/反序列化，Asp.net为String、Integer、Boolean等基本类型的序列化做了优化，如果Array、ArrayList、HashTable存储的是基本类型效率也较高，但其它类型则需要提供类型转换器（Type Converter），否则将使用代价昂贵的二进制序列化程序。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.JScript &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.1 JScript性能优化的基本原则&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽可能少地减少执行次数。毕竟对解释语言来说，每一个执行步骤，都需要和解释引擎做一次交互。&lt;/p&gt;&#xD;
&lt;p&gt;2. 尽可能使用语言内置的功能，比如串链接。&lt;/p&gt;&#xD;
&lt;p&gt;3. 尽可能使用系统提供的API来进行优化。因为这些API是编译好的二进制代码，执行效率很高。&lt;/p&gt;&#xD;
&lt;p&gt;4. 书写最正确的代码。容错功能是要付出性能代价的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.2 JScript语言本身的优化&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.1 变量&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽量使用局部变量。&lt;/p&gt;&#xD;
&lt;p&gt;因为全局变量其实是全局对象的成员，而局部变量在栈上定义，优先查找，性能相对于全局变量要高。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 尽量在一个语句中做定义变量和赋值。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 省略不必要的变量定义。&lt;/p&gt;&#xD;
&lt;p&gt;如果变量的定义可以被一个常量替代，就直接使用常量。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 使用Object语法对对象赋值。&lt;/p&gt;&#xD;
&lt;p&gt;Object的赋值语法在操作复杂对象时效率更高。&lt;/p&gt;&#xD;
&lt;p&gt;例如，可以将下面的代码：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;car = new Object();&lt;/p&gt;&#xD;
&lt;p&gt;car.make = "Honda";&lt;/p&gt;&#xD;
&lt;p&gt;car.model = "Civic";&lt;/p&gt;&#xD;
&lt;p&gt;car.transmission = "manual";&lt;/p&gt;&#xD;
&lt;p&gt;car.miles = 100000;&lt;/p&gt;&#xD;
&lt;p&gt;car.condition = "needs work";&lt;/p&gt;&#xD;
&lt;p&gt;替换成：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;car = {&lt;/p&gt;&#xD;
&lt;p&gt;make: "Honda",&lt;/p&gt;&#xD;
&lt;p&gt;model: "Civic",&lt;/p&gt;&#xD;
&lt;p&gt;transmission: "manual",&lt;/p&gt;&#xD;
&lt;p&gt;miles: 100000,&lt;/p&gt;&#xD;
&lt;p&gt;condition: "needs work"&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.2 对象缓存&lt;/p&gt;&#xD;
&lt;p&gt;1. 缓存对象查找的中间结果。&lt;/p&gt;&#xD;
&lt;p&gt;因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 缓存创建时间较长的对象。&lt;/p&gt;&#xD;
&lt;p&gt;自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.3 字符串操作&lt;/p&gt;&#xD;
&lt;p&gt;1. 使用"+=" 追加字符串，使用"+"来连接字符串。&lt;/p&gt;&#xD;
&lt;p&gt;如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。&lt;/p&gt;&#xD;
&lt;p&gt;如果要连接多个字符串，应该使用"+"，如：&lt;/p&gt;&#xD;
&lt;p&gt;s+=a;&lt;/p&gt;&#xD;
&lt;p&gt;s+=b;&lt;/p&gt;&#xD;
&lt;p&gt;s+=c;&lt;/p&gt;&#xD;
&lt;p&gt;应该写成&lt;/p&gt;&#xD;
&lt;p&gt;s+=a + b + c；&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 连接大量的字符串，应使用Array的join方法。&lt;/p&gt;&#xD;
&lt;p&gt;如果是收集字符串，最好使用JavaScript数组缓存，最后使用join方法连接起来，如下：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;var buf = new Array();&lt;/p&gt;&#xD;
&lt;p&gt;for (var i = 0; i &amp;lt; 100; i++)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;buf.push(i.toString());&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;var all = buf.join("");&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.4 类型转换&lt;/p&gt;&#xD;
&lt;p&gt;1. 使用Math.floor()或者Math.round()将浮点数转换成整型。&lt;/p&gt;&#xD;
&lt;p&gt;浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。&lt;/p&gt;&#xD;
&lt;p&gt;对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 自定义的对象，推荐定义和使用toString()方法来进行类型转换。&lt;/p&gt;&#xD;
&lt;p&gt;对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()。因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.5 循环的优化&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽可能少使用for(in)循环。&lt;/p&gt;&#xD;
&lt;p&gt;在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 预先计算collection的length。&lt;/p&gt;&#xD;
&lt;p&gt;如：将for (var i = 0; i &amp;lt; collection.length; i++)&lt;/p&gt;&#xD;
&lt;p&gt;替换成：for (var i = 0, len = collection.length; i &amp;lt; len; i++)&lt;/p&gt;&#xD;
&lt;p&gt;效果会更好，尤其是在大循环中。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 尽量减少循环内的操作。&lt;/p&gt;&#xD;
&lt;p&gt;循环内的每个操作，都会被放大为循环次数的倍数。所以，大循环内微小的改进，在性能的整体提升上都是可观的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 使用循环替代递归。&lt;/p&gt;&#xD;
&lt;p&gt;相比循环，递归的效率更差一些。递归的优点是在形式上更自然一些。所以，在不影响代码的维护性的前提下，用循环替代递归。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2.6 其它方面&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽量使用语言内置的语法。&lt;/p&gt;&#xD;
&lt;p&gt;"var arr = [&amp;hellip;];"和"var arr = new Array(&amp;hellip;);"是等效的，但是前者的效能优于后者。同样，"var foo = {};"的方式也比"var foo = new Object();"快；"var reg = /../;"要比"var reg=new RegExp()"快。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 尽量不要使用eval。&lt;/p&gt;&#xD;
&lt;p&gt;使用eval，相当于在运行时再次调用解释引擎，对传入的内容解释运行，需要消耗大量时间。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;3. 使用prototype代替closure。&lt;/p&gt;&#xD;
&lt;p&gt;使用closure在性能和内存消耗上都是不利的。如果closure使用量过大，这就会成为一个问题。所以，尽量将：&lt;/p&gt;&#xD;
&lt;p&gt;this.methodFoo = function()&lt;/p&gt;&#xD;
&lt;p&gt;替换成：&lt;/p&gt;&#xD;
&lt;p&gt;MyClass.protoype.methodFoo = function()&lt;/p&gt;&#xD;
&lt;p&gt;和closure存在于对象实例之中不同，prototype存在于类中，被该类的所有的对象实例共享。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 避免使用with语句。&lt;/p&gt;&#xD;
&lt;p&gt;With语句临时扩展对象查找的范围，节省了文字的录入时间，但付出了更多的执行时间。因为每个给出的名称都要在全局范围查找。所以，可以将下面的代码：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;with (document.formname)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;field1.value = "one";&lt;/p&gt;&#xD;
&lt;p&gt;field2.value = "two";&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;变更为：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;var form = document.formname;&lt;/p&gt;&#xD;
&lt;p&gt;form.field1.value = "one";&lt;/p&gt;&#xD;
&lt;p&gt;form.field2.value = "two";&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.3 DOM相关&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.3.1 创建DOM节点&lt;/p&gt;&#xD;
&lt;p&gt;相比较通过document.write来给页面生成内容，找一个容器元素（比如指定一个div或者span）并设置他们的innerHTML效率更高。&lt;/p&gt;&#xD;
&lt;p&gt;而设置innerHTML的方式比通过createElement方法创建节点的效率更高。事实上，设置元素的innerHTML是创建节点效率最高的一种方式。&lt;/p&gt;&#xD;
&lt;p&gt;如果必须使用createElement方法，而如果文档中存在现成的样板节点，应该是用cloneNode()方法。因为使用createElement()方法之后，你需要设置多次元素的属性，使用cloneNode()则可以减少属性的设置次数。同样，如果需要创建很多元素，应该先准备一个样板节点。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.3.2 离线操作大型的DOM树&lt;/p&gt;&#xD;
&lt;p&gt;在添加一个复杂的DOM树时，可以先构造，构造结束后再将其添加到DOM数的适当节点。这能够节省界面刷新的时间。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;同样，在准备编辑一个复杂的树时，可以先将树从DOM树上删除，等编辑结束后再添加回来。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.3.3 对象查询&lt;/p&gt;&#xD;
&lt;p&gt;使用[""]查询要比.item()更快。调用.item()增加了一次查询和函数的调用。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.3.4 定时器&lt;/p&gt;&#xD;
&lt;p&gt;如果针对的是不断运行的代码，不应该使用setTimeout，而应该用setInterval。setTimeout每次要重新设置一个定时器。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.4 其他&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. 尽量减小文件尺寸。&lt;/p&gt;&#xD;
&lt;p&gt;将JScript文件中无关的空行、空格、注释去掉，有助于减小JS文件的尺寸，提高下载的时间。（可以通过工具来支持代码发布）&lt;/p&gt;&#xD;
&lt;p&gt;2. 尽量不要在同一个Page内同时引用JScript和VBScript引擎&lt;/p&gt;&#xD;
&lt;p&gt;3. 将Page内的JScript移入到单独的JS文件中。&lt;/p&gt;&#xD;
&lt;p&gt;4. 将Page内的JScript放置在Page的最下面，有助于提高页面的响应速度。&lt;/p&gt;&#xD;
&lt;p&gt;5. 利用cache，减少JScript文件的下载次数&lt;/p&gt;&#xD;
&lt;p&gt;6. 在HTML内书写JScript文件的URL时，注意统一大小写。这样可以利用前面URL缓存的文件。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1918820.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1918820.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1918819.html</id><title type="text">14条让你的网页加速</title><summary type="text">Steve Souders这个家伙写了一本书叫做：High Performance Web Sites: Essential Knowledge for Front-End Engineers这本书里定义了14条让你的网页加速的方法，分别如下：1. Make fewer HTTP requests2. Use a CDN3. Add an Expires header4. Gzip components5. Put CSS at the top6. Move JS to the bottom7. Avoid CSS expressions8. Make JS and CSS external9</summary><published>2010-12-28T05:23:00Z</published><updated>2010-12-28T05:23:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1918819.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1918819.html"/><content type="html">&lt;p&gt;Steve Souders这个家伙写了一本书叫做：High Performance Web Sites: Essential Knowledge for Front-End Engineers&lt;br /&gt;这本书里定义了14条让你的网页加速的方法，分别如下：&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Make fewer HTTP requests&lt;/p&gt;&#xD;
&lt;p&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Use a CDN&lt;/p&gt;&#xD;
&lt;p&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Add an Expires header&lt;/p&gt;&#xD;
&lt;p&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Gzip components&lt;/p&gt;&#xD;
&lt;p&gt;5.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Put CSS at the top&lt;/p&gt;&#xD;
&lt;p&gt;6.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Move JS to the bottom&lt;/p&gt;&#xD;
&lt;p&gt;7.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Avoid CSS expressions&lt;/p&gt;&#xD;
&lt;p&gt;8.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Make JS and CSS external&lt;/p&gt;&#xD;
&lt;p&gt;9.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Reduce DNS lookups&lt;/p&gt;&#xD;
&lt;p&gt;10.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Minify JS&lt;/p&gt;&#xD;
&lt;p&gt;11.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Avoid redirects&lt;/p&gt;&#xD;
&lt;p&gt;12.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Remove duplicate scripts&lt;/p&gt;&#xD;
&lt;p&gt;13.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Turn off ETags&lt;/p&gt;&#xD;
&lt;p&gt;14.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Make AJAX cacheable and small&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1. Make fewer HTTP requests&lt;/p&gt;&#xD;
&lt;p&gt;-减少Image的Request次数&lt;/p&gt;&#xD;
&lt;p&gt;-使用CSS Sprites技巧http://alistapart.com/articles/sprites&lt;/p&gt;&#xD;
&lt;p&gt;-使用Image Map技巧&lt;/p&gt;&#xD;
&lt;p&gt;-使用Inline Image技巧( data: ) http://tools.ietf.org/html/rfc2397&lt;/p&gt;&#xD;
&lt;p&gt;P.S.可以开发一个Inline Image产生器！&lt;/p&gt;&#xD;
&lt;p&gt;PS建议将Inline Image快取在CSS档案中，这样可避免HTML太大&lt;/p&gt;&#xD;
&lt;p&gt;-减少CSS / JavaScript的Request次数&lt;/p&gt;&#xD;
&lt;p&gt;-整合多个分开的CSS / JavaScript&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;2. Use a CDN&lt;/p&gt;&#xD;
&lt;p&gt;N/A&lt;/p&gt;&#xD;
&lt;p&gt;3. Add an Expires header&lt;/p&gt;&#xD;
&lt;p&gt;-加入Expires Header到Image, CSS, JavaScript档案里&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;4. Gzip components&lt;/p&gt;&#xD;
&lt;p&gt;-压缩HTML, JavaScript, StyleSheet, XML, JSON，但切记「不要压缩Images, PDF档案」！&lt;/p&gt;&#xD;
&lt;p&gt;-设定方法&lt;/p&gt;&#xD;
&lt;p&gt;Apache 2.x:使用mod_deflate：&lt;/p&gt;&#xD;
&lt;p&gt;AddOutputFilterByType DEFLATE text/html text/css application/x-javascript&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;IIS 6.0&lt;/p&gt;&#xD;
&lt;p&gt;Enabling HTTP Compression (IIS 6.0)&lt;/p&gt;&#xD;
&lt;p&gt;http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;Using HTTP Compression for Faster Downloads (IIS 6.0)&lt;/p&gt;&#xD;
&lt;p&gt;http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/25d2170b-09c0-45fd-8da4-898cf9a7d568.mspx?mfr=true&lt;/p&gt;&#xD;
&lt;p&gt;Enabling HTTP Compression in IIS 6.0&lt;/p&gt;&#xD;
&lt;p&gt;http://dotnetjunkies.com/Article/16267D49-4C6E-4063-AB12-853761D31E66.dcik&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;IIS Compression in IIS6.0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx&lt;br /&gt;IIS 5.0&lt;br /&gt;HOW TO：启用IIS中的ASPX压缩&lt;/p&gt;&#xD;
&lt;p&gt;http://support.microsoft.com/kb/322603&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;- HTTP Header Style&lt;/p&gt;&#xD;
&lt;p&gt;HTTP request&lt;/p&gt;&#xD;
&lt;p&gt;Accept-Encoding: gzip, deflate&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTTP response&lt;/p&gt;&#xD;
&lt;p&gt;Content-Encoding: gzip&lt;/p&gt;&#xD;
&lt;p&gt;Vary: Accept-Encoding (这行是给Proxy Server看的)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;-其他注意事项&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;-个人化的页面要加上==&amp;gt; Cache-Control: Private&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;-移除ETags (Rule 13)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;5. Put CSS at the top&lt;/p&gt;&#xD;
&lt;p&gt;-一定要将CSS放在区段载入!&lt;/p&gt;&#xD;
&lt;p&gt;-使用标签，不要使用@import语法&lt;/p&gt;&#xD;
&lt;p&gt;- Avoid Flash of Unstyled Content (FOUC) in IE&lt;/p&gt;&#xD;
&lt;p&gt;http://www.bluerobot.com/web/css/fouc.asp/&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;6. Move JS to the bottom&lt;/p&gt;&#xD;
&lt;p&gt;-一定要将所有JavaScript都摆在页面最下方之前&lt;/p&gt;&#xD;
&lt;p&gt;所有在JavaScript Include以下的HTML在JS还没读完前，都不会显示画面&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;-把JavaScript的Code都放在onload执行！ ！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;7. Avoid CSS expressions&lt;/p&gt;&#xD;
&lt;p&gt;-不要使用CSS expressions&lt;/p&gt;&#xD;
&lt;p&gt;可能这段expression会在每一次mouse move, resize, scroll, key press时执行!&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;-要使用EventHandler去执行这些Expression (JS Code)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;8. Make JS and CSS external&lt;/p&gt;&#xD;
&lt;p&gt;-反正JS跟CSS拉到外面成独立档案就是好的，但「首页」可以例外！&lt;/p&gt;&#xD;
&lt;p&gt;-使用Post-onload download技巧&lt;/p&gt;&#xD;
&lt;p&gt;download external files after onload&lt;/p&gt;&#xD;
&lt;p&gt;window.onload = downloadComponents;&lt;/p&gt;&#xD;
&lt;p&gt;function downloadComponents() {&lt;/p&gt;&#xD;
&lt;p&gt;var elem = document.createElement(&amp;ldquo;script&amp;rdquo;);&lt;/p&gt;&#xD;
&lt;p&gt;elem.src = &amp;ldquo;http://&amp;hellip;/file1.js&amp;rdquo;;&lt;/p&gt;&#xD;
&lt;p&gt;document.body.appendChild(elem);&lt;/p&gt;&#xD;
&lt;p&gt;&amp;hellip;&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;范例：http://stevesouders.com/hpws/dynamic-inlining.php&lt;/p&gt;&#xD;
&lt;p&gt;作法：&lt;/p&gt;&#xD;
&lt;p&gt;1.在Server-side判断使用者Browser有设定Cookie["hasPostOnloadDownload"]&lt;/p&gt;&#xD;
&lt;p&gt;1.1.若没有，就使用post-onload download动态下载CSS &amp;amp; JS&lt;/p&gt;&#xD;
&lt;p&gt;1.2.若有用，就直接用下载，Browser会抓取Cache的版本&lt;/p&gt;&#xD;
&lt;p&gt;P.S. cookie expiration date is key&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;9. Reduce DNS lookups&lt;/p&gt;&#xD;
&lt;p&gt;-在一个页面中，不要超过2 &amp;ndash; 4个Hostname，不然会降低页面载入速度&lt;/p&gt;&#xD;
&lt;p&gt;-开启Keep-Alive支援&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;10. Minify JS&lt;/p&gt;&#xD;
&lt;p&gt;- jsmin : http://crockford.com/javascript/jsmin&lt;/p&gt;&#xD;
&lt;p&gt;下载后更名成jsmin.zip解压缩出jsmin.exe即可执行,jsmin.exe &amp;lt; input.js &amp;gt; output.js (注意：所有UTF-8编码的js档会变成ANSI as UTF-8编码)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;- dojo compressor : http://dojotoolkit.org/docs/shrinksafe&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;11. Avoid redirects&lt;/p&gt;&#xD;
&lt;p&gt;-参考资料：http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html&lt;/p&gt;&#xD;
&lt;p&gt;-避免Redirect产生的方式&lt;/p&gt;&#xD;
&lt;p&gt;*网址若省略档名时，最后面一定要加上/结尾&lt;/p&gt;&#xD;
&lt;p&gt;*追查Log档&lt;/p&gt;&#xD;
&lt;p&gt;-查看Log Referer&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;12. Remove duplicate scripts&lt;/p&gt;&#xD;
&lt;p&gt;-这一点虽然很呆，不过连MSN Space, Yahoo都有类似的情况！&lt;/p&gt;&#xD;
&lt;p&gt;-在ASP.NET的元件中(UserControls, WebControls)，请多使用Page.ClientScript.RegisterScriptInclude的方式！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;13. Turn off ETags&lt;/p&gt;&#xD;
&lt;p&gt;-基本格式&lt;/p&gt;&#xD;
&lt;p&gt;* unique identifier returned in response&lt;/p&gt;&#xD;
&lt;p&gt;ETag: &amp;ldquo;c8897e-aee-4165acf0&amp;Prime;&lt;/p&gt;&#xD;
&lt;p&gt;Last-Modified: Thu, 07 Oct 2004 20:54:08 GMT&lt;/p&gt;&#xD;
&lt;p&gt;* used in conditional GET requests&lt;/p&gt;&#xD;
&lt;p&gt;If-None-Match: &amp;ldquo;c8897e-aee-4165acf0&amp;Prime;&lt;/p&gt;&#xD;
&lt;p&gt;If-Modified-Since: Thu, 07 Oct 2004 20:54:08 GMT&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;- if ETag doesn't match, can't send 304&lt;/p&gt;&#xD;
&lt;p&gt;- ETag format&lt;/p&gt;&#xD;
&lt;p&gt;Apache: ETag: inode-size-timestamp&lt;/p&gt;&#xD;
&lt;p&gt;IIS: ETag: Filetimestamp:ChangeNumber&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;- IIS设定方式&lt;/p&gt;&#xD;
&lt;p&gt;自动设定方式&lt;/p&gt;&#xD;
&lt;p&gt;ETagFix &amp;ndash; keep IIS eTags from changing http://www.snapfiles.com/get/etagfix.html&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;原创公司：ISAPILab http://www.isapilabs.com/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;安装http://www.isapilabs.com/downloads/ETagFix-setup.exe之后会重新启动IIS之后就没问题了！&lt;/p&gt;&#xD;
&lt;p&gt;Related: http://www.snapfiles.com/Freeware/server/fwiis.html&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Note:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;在IIS 5.0可以正常运作&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;在IIS 6.0必须要执行在Isolate Mode才可以使用ISAPI，预设是不能用的！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;手动设定方式&lt;/p&gt;&#xD;
&lt;p&gt;*如果不是用Windows Server 2003 SP1要先安装Hotfix 900245 http://support.microsoft.com/kb/900245/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;*先安装IIS 6.0 Resource Kit&lt;/p&gt;&#xD;
&lt;p&gt;http://www.microsoft.com/downloads/details.aspx?FamilyId=56FC92EE-A71A-4C73-B628-ADE629C89499&amp;amp;displaylang=en&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;*使用Metabase Explorer开启LM &amp;rdquo; W3SVC新增DWORD to 2039其Value=&amp;rdquo;0&amp;Prime; (每一台WebFarm底下的电脑都要这样设定)&lt;/p&gt;&#xD;
&lt;p&gt;*重新启动IIS&lt;/p&gt;&#xD;
&lt;p&gt;net stop iisadmin /y&lt;/p&gt;&#xD;
&lt;p&gt;net start w3svc&lt;/p&gt;&#xD;
&lt;p&gt;net start smtpsvc&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;参考资料&lt;/p&gt;&#xD;
&lt;p&gt;*您可能会当您使用Internet Explorer 6，试着存取Web应用程式所装载在Internet Information Services 6.0 Web效能非常低&lt;/p&gt;&#xD;
&lt;p&gt;http://support.microsoft.com/kb/922703/&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;- Apache设定方式&lt;/p&gt;&#xD;
&lt;p&gt;FileETag none&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;14. Make AJAX cacheable and small&lt;/p&gt;&#xD;
&lt;p&gt;- XHR, JSON, iframe, dynamic scripts都一样可以被快取(Cached)、最小化(minified)和压缩(gzipped)&lt;/p&gt;&#xD;
&lt;p&gt;-个人化的页面回应时，一样要做快取，但是针对「该使用者」做快取(Cache-Control: private)&lt;/p&gt;&#xD;
&lt;p&gt;-在使用XHR时，URL可以加上「最近的修改时间」在QueryString里。&lt;/p&gt;&#xD;
&lt;p&gt;GET /yab/[...]&amp;amp;r=0.5289571053069156 HTTP/1.1&lt;/p&gt;&#xD;
&lt;p&gt;-回传资料时的Header可以用Cache-Control: private + Last-Modified，使用者就不会一直连到网站抓网站了!!&lt;/p&gt;&#xD;
&lt;p&gt;设定Cache Header注意事项:&lt;/p&gt;&#xD;
&lt;p&gt;*个人化的页面一定要设定Response.Cache.SetCacheability(HttpCacheability.Private);&lt;/p&gt;&#xD;
&lt;p&gt;*如果要Cache页面或External Reference档案(CSS/JS)一定要加上Response.Cache.SetLastModified(DateTime.Now);&lt;/p&gt;&#xD;
&lt;p&gt;*如果不加上MaxAge的话，将会无限时间的Cache直到下次Reload或开新Browser手动输入网址进入网页&lt;/p&gt;&#xD;
&lt;p&gt;*如果要指定Cache的时间要加上&lt;/p&gt;&#xD;
&lt;p&gt;Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, 10));&lt;/p&gt;&#xD;
&lt;p&gt;Response.Cache.SetExpires(DateTime.Now.AddSeconds(10));&lt;/p&gt;&#xD;
&lt;p&gt;*如果不要页面被Cache的话&lt;/p&gt;&#xD;
&lt;p&gt;Response.Cache.SetMaxAge(TimeSpan.Zero);&lt;/p&gt;&#xD;
&lt;p&gt;Response.Cache.SetExpires(DateTime.MinValue);&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1918819.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1918819.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1902093.html</id><title type="text">[转载]高性能WEB开发</title><summary type="text">[1] HTTP服务器篇[2] web 性能测试工具推荐[3] 图片篇[4] 如何加载JS，JS应该放在什么位置？[5] 为什么要减少请求数，如何减少请求数![6] 减少请求，响应的数据量[7] JS、 CSS的合并、压缩、缓存管理[8] 页面呈现、重绘、回流</summary><published>2010-12-10T03:11:00Z</published><updated>2010-12-10T03:11:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1902093.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1902093.html"/><content type="html">&lt;p&gt;[1] &lt;a href="http://kb.cnblogs.com/page/64064/" target="_blank"&gt;HTTP服务器篇&lt;/a&gt;&lt;br /&gt;[2] &lt;a  href="http://kb.cnblogs.com/page/64064/2/" target="_blank"&gt;web 性能测试工具推荐&lt;/a&gt;&lt;br /&gt;[3] &lt;a  href="http://kb.cnblogs.com/page/64064/3/" target="_blank"&gt;图片篇&lt;/a&gt;&lt;br /&gt;[4] &lt;a  href="http://kb.cnblogs.com/page/64064/4/" target="_blank"&gt;如何加载JS，JS应该放在什么位置？&lt;/a&gt;&lt;br /&gt;[5] &lt;a  href="http://kb.cnblogs.com/page/64064/5/" target="_blank"&gt;为什么要减少请求数，如何减少请求数!&lt;/a&gt;&lt;br /&gt;[6] &lt;a  href="http://kb.cnblogs.com/page/64064/6/" target="_blank"&gt;减少请求，响应的数据量&lt;/a&gt;&lt;br /&gt;[7] &lt;a  href="http://kb.cnblogs.com/page/64064/7/" target="_blank"&gt;JS、 CSS的合并、压缩、缓存管理&lt;/a&gt;&lt;br /&gt;[8] &lt;a  href="http://kb.cnblogs.com/page/64064/8/" target="_blank"&gt;页面呈现、重绘、回流&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1902093.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1902093.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1887032.html</id><title type="text">[转]在VS2008中使用WSE 3.0过程全记录</title><summary type="text">该篇文章是我于2009年6月10日通过自己编写的工具，批量从位于在博客园的博客站点(http://chenxizhang.cnblogs.com)同步而来。文章中的图片地址仍然是链接到博客园的。特此说明！陈希章原文地址：http://www.cnblogs.com/chenxizhang/archive/2009/05/12/1455187.html原文标题：在VS2008中使用WSE 3.0过程...</summary><published>2010-11-24T13:18:00Z</published><updated>2010-11-24T13:18:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1887032.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1887032.html"/><content type="html">&lt;p&gt;该篇文章是我于2009年6月10日通过自己编写的工具，批量从位于在博客园的博客站点(&lt;a href="http://chenxizhang.cnblogs.com/"&gt;http://chenxizhang.cnblogs.com&lt;/a&gt;)同步而来。文章中的图片地址仍然是链接到博客园的。特此说明！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;陈希章&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;原文地址：&lt;a href="http://www.cnblogs.com/chenxizhang/archive/2009/05/12/1455187.html"&gt;http://www.cnblogs.com/chenxizhang/archive/2009/05/12/1455187.html&lt;/a&gt;&lt;br /&gt;原文标题：在VS2008中使用WSE 3.0过程全记录&lt;br /&gt;原文发表：2009/5/12 11:50:00&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;WSE全称是Web Service Enhancement，提供了更好的安全性实现，以及大对象传输的设计。&lt;/p&gt;&#xD;
&lt;p&gt;有关WSE的一些介绍，如果不清楚，可以参考下面的链接 &lt;/p&gt;&#xD;
&lt;p&gt;官方介绍：&lt;a href="http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/WSESecurity.mspx?mfr=true"&gt;http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/WSESecurity.mspx?mfr=true&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;下载位置：&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;amp;DisplayLang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;amp;DisplayLang=en&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这两天讲课中又提到了WSE。现在我们用的是VS2008，与之前VS2005还有一点不一样。所以，今天我再次将使用步骤做一个完整的记录&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第一部分：准备证书&lt;/p&gt;&#xD;
&lt;p&gt;WSE是需要证书的。证书是用来对消息进行加密和签名的。作为测试目的，可以通过makecert这个工具来做&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_10.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_4.png" border="0" alt="image" width="820" height="620" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;我自己写了一个bat文件，内容如下&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;REM 这个脚本用来创建一个测试的证书  &lt;/p&gt;&#xD;
&lt;p&gt;REM 作者：陈希章  &lt;/p&gt;&#xD;
&lt;p&gt;set CERTNAME=&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;TestServiceCert&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;certmgr -del -r LocalMachine -s My -c -n %CERTNAME%&lt;br /&gt;makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=%CERTNAME% -sky exchange -pe&lt;br /&gt;set WP_ACCOUNT=NETWORK SERVICE&lt;br /&gt;(ver | findstr "5.1") &amp;amp;&amp;amp; set WP_ACCOUNT=%COMPUTERNAME%\ASPNET&lt;br /&gt;winhttpcertcfg -g -c LOCAL_MACHINE\My -s %CERTNAME% -a "%WP_ACCOUNT%"&lt;/p&gt;&#xD;
&lt;p&gt;REM 授予IIS帐号对该证书的访问权限&lt;br /&gt;iisreset&lt;br /&gt;pause &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;红色的部分，你可以修改成自己想要的名称&lt;/p&gt;&#xD;
&lt;p&gt;创建好证书之后&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_12.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_5.png" border="0" alt="image" width="1070" height="763" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第二部分：创建和配置服务&lt;/p&gt;&#xD;
&lt;p&gt;1. 创建服务。&lt;/p&gt;&#xD;
&lt;p&gt;【注意】经过反复测试，必须使用网站模板，而不是项目模板创建Web Service&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_114.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_56.png" border="0" alt="image" width="703" height="471" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 在服务项目中，添加对Microsoft.Web.Service3.dll的引用&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_6.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_2.png" border="0" alt="image" width="502" height="385" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;【备注】该程序集的位置在&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_8.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_3.png" border="0" alt="image" width="820" height="620" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_48.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_23.png" border="0" alt="image" width="227" height="281" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;3. 通过Configuration Tool配置服务。在VS2005的时候，这个工具可以集成到IDE中。而VS2008则不可以&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_14.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_6.png" border="0" alt="image" width="613" height="184" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_16.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_7.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;选择&amp;rdquo;File&amp;rdquo;==》&amp;ldquo;Open&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_18.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_8.png" border="0" alt="image" width="583" height="439" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;在General页面中选中两个选项&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_20.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_9.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;在Security页面，注意选中Allow Test Root，因为我们用的证书是一个测试的，不受信任的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_22.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_10.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;在Policy页面，启用Policy&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_24.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_11.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;下面，我们准备创建一个策略。点击&amp;rdquo;Add&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_26.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_12.png" border="0" alt="image" width="396" height="194" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;输入一个名称，然后点击&amp;rdquo;OK&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_28.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_13.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_30.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_14.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这向导的这个页面，选择&amp;rdquo;Secure a Service Application&amp;rdquo;， 并且选择客户端验证方法为&amp;rdquo;UserName&amp;rdquo;(这种方式其实使用服务器的Windows帐号作为凭据的）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_32.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_15.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这个页面可以做授权(Authorization)。我们这里不做指定&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_34.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_16.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这个页面我们保留所有默认值&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_36.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_17.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这个页面中点击&amp;rdquo;Select Certificate&amp;rdquo; ，&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_38.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_18.png" border="0" alt="image" width="443" height="287" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;选择我们刚才创建的证书：TestServiceCert, 然后点击&amp;ldquo;确定&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_40.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_19.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;Finish&amp;rdquo;，即可完成所有的配置&lt;/p&gt;&#xD;
&lt;p&gt;完成之后，选择&amp;rdquo;File&amp;rdquo; ==》&amp;ldquo;Save&amp;rdquo;来保存配置&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_42.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_20.png" border="0" alt="image" width="533" height="167" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;然后，可以关闭Configuration Tool,回到Visual Studio环境中。这个Service很简单，我们也不准备做任何修改。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_46.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_22.png" border="0" alt="image" width="1056" height="800" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_50.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_24.png" border="0" alt="image" width="247" height="207" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;显示所有文件&amp;rdquo;这个按钮，我们会发现多了一个文件：wse3policyCache.config&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_52.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_25.png" border="0" alt="image" width="220" height="206" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;选择该文件，点击右键，选择&amp;rdquo;包含在项目中&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_54.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_26.png" border="0" alt="image" width="220" height="195" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;双击打开该文件。这是一个附加的配置文件，我们刚才所做的配置都记录在该文件中。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_56.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_27.png" border="0" alt="image" width="1056" height="800" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;我们还可以双击Web.config，看看有什么变化&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_58.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_28.png" border="0" alt="image" width="1056" height="800" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;4. 在服务上面应用策略&lt;/p&gt;&#xD;
&lt;p&gt;完成了策略配置之后，接下来我们就是为服务应用策略了。&lt;/p&gt;&#xD;
&lt;p&gt;转到Service1.asmx.cs文件&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_60.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_29.png" border="0" alt="image" width="1053" height="641" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;到这里为止，服务端的配置就完成了。此时，请编译项目。（Ctrl+Shift+B) &lt;/p&gt;&#xD;
&lt;p&gt;接下来我们需要创建客户端进行测试&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第三部分：创建客户端并且进行测试&lt;/p&gt;&#xD;
&lt;p&gt;1. 在解决方案中添加一个Windows Forms应用程序&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_62.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_30.png" border="0" alt="image" width="542" height="450" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_64.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_31.png" border="0" alt="image" width="703" height="466" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;2. 添加Web Service引用&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_66.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_32.png" border="0" alt="image" width="260" height="98" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_68.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_33.png" border="0" alt="image" width="837" height="656" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;此解决方案中的Web 服务&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_70.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_34.png" border="0" alt="image" width="837" height="656" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;Service1&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_72.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_35.png" border="0" alt="image" width="837" height="656" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;添加引用&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_74.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_36.png" border="0" alt="image" width="269" height="281" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;3. 编写代码访问HelloWorld方法&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_76.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_37.png" border="0" alt="image" width="633" height="122" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 运行Client程序，进行调试&lt;/p&gt;&#xD;
&lt;p&gt;将Client项目设置为启动项目&lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_78.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_38.png" border="0" alt="image" width="355" height="590" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;然后，按F5键进行调试&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_80.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_39.png" border="0" alt="image" width="320" height="320" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;点击&amp;ldquo;调用服务&amp;rdquo;，我们会遇到一个异常，如下&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_82.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_40.png" border="0" alt="image" width="476" height="327" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_84.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_41.png" border="0" alt="image" width="1049" height="736" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;为什么会出现这样的异常呢？&lt;/p&gt;&#xD;
&lt;p&gt;原因很简单：服务器端已经启用了WSE，而客户端并没有启用。所以，接下来，我们得完成客户端的配置&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;5. 运行configuration Tool对客户端进行配置。&lt;/p&gt;&#xD;
&lt;p&gt;通过&amp;rdquo;File&amp;rdquo; =&amp;gt;&amp;rdquo;Open&amp;rdquo;打开Client项目的app.config&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_86.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_42.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;General页面中只能选中第一个选项。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_88.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_43.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Security页面中照样要选中&amp;ldquo;Allow test roots&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_90.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_44.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Policy页面中启用Policy后，点击&amp;ldquo;add&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_92.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_45.png" border="0" alt="image" width="396" height="194" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;输入名称，点击&amp;ldquo;Ok&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_94.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_46.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_96.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_47.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这个页面中选择&amp;ldquo;Secure a client application&amp;rdquo;，并且设置验证方法为&amp;rdquo;UserName&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_98.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_48.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;保留默认值，在代码中指定用户的凭据&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_100.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_49.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;保留默认值&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_102.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_50.png" border="0" alt="image" width="602" height="424" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;【注意】这里要选择与服务器相同的证书。点击Next，然后点击Finish&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_104.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_51.png" border="0" alt="image" width="535" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;最后，完成保存后关闭Configuration Tool&lt;/p&gt;&#xD;
&lt;p&gt;回到Visual Studio之后，将wse3policyCache.config文件包含到项目中&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_110.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_54.png" border="0" alt="image" width="275" height="277" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;并且设置该文件的属性。复制到输出目录&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_112.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_55.png" border="0" alt="image" width="220" height="168" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;6. 在Client项目也添加对Microsoft.Web.Service3.dll的引用&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_6.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_2.png" border="0" alt="image" width="502" height="385" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;7. 修改Web引用的代理文件&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_106.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_52.png" border="0" alt="image" width="322" height="308" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;双击Reference.cs&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_108.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_53.png" border="0" alt="image" width="1055" height="473" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;添加一个using语句。并且将Service1这个类的基类修改为WebServiceClientProtocol.保存该文件，重新编译&lt;/p&gt;&#xD;
&lt;p&gt;8. 修改窗体代码&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_116.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_57.png" border="0" alt="image" width="586" height="208" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;9. 再一次进行调试。我们就可以正常看到一个对话框  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_118.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_58.png" border="0" alt="image" width="124" height="126" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第四部分：查看加密的消息。  &lt;/p&gt;&#xD;
&lt;p&gt;我们知道现在的消息是通过证书加密的，但事实上是不是真的加密了呢？我们可以通过Configuration Tool再次打开客户端的配置文件app.config  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_120.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_59.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;在Diagnostics页面，Enable Message Trace  &lt;/p&gt;&#xD;
&lt;p&gt;然后保存该文件。重新调试客户端。此时会生成两个文件。  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_124.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_61.png" border="0" alt="image" width="820" height="620" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;我们可以打开InputTrace.webinfo看一下。在SOAPBody里面的内容已经经过了加密  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_122.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_60.png" border="0" alt="image" width="1020" height="890" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;SOAPHeader里面包含了我们的用户名和密码，毫无疑问，也是经过了加密的  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;第五部分：使用自定义的UserNameTokenManager  &lt;/p&gt;&#xD;
&lt;p&gt;上面的例子很成功，但目前它所使用的用户凭据是Windows凭据。如果我们想自定义身份验证，应该怎么办呢？  &lt;/p&gt;&#xD;
&lt;p&gt;1. 创建自定义的UserNameTokenManager.  &lt;/p&gt;&#xD;
&lt;p&gt;我们可以创建一个单独的类库项目  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_126.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_62.png" border="0" alt="image" width="703" height="466" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;在该项目中，添加对Microsoft.Web.Service3.dll的引用  &lt;/p&gt;&#xD;
&lt;p&gt;创建一个类型，代码大致如下  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_128.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_63.png" border="0" alt="image" width="850" height="568" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;编译该项目。  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2. 在服务项目中添加上述程序集的引用  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_130.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_64.png" border="0" alt="image" width="502" height="385" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;3. 重新用Configuration Tool对服务的Web.config进行配置。定位到&amp;ldquo;Security&amp;rdquo;页面  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_132.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_65.png" border="0" alt="image" width="536" height="562" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;在Security Tokens Managers的位置，点击&amp;rdquo;Add&amp;rdquo;  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_134.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_66.png" border="0" alt="image" width="518" height="320" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;在Built in Token Managers中选择&amp;ldquo;UserNameTokenManager&amp;rdquo;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_136.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_67.png" border="0" alt="image" width="514" height="305" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;将Type修改为  &lt;/p&gt;&#xD;
&lt;p&gt;MyUserNameTokenManger.MyUserNameTokenManger,MyUserNameTokenManger  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_138.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb_68.png" border="0" alt="image" width="518" height="320" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;保存修改之后，在web.config中可以发现下面的变化&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&amp;nbsp; &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;namespace="&lt;/span&gt;&lt;/strong&gt;&lt;a href="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt; localName="UsernameToken"&lt;/span&gt;&lt;/strong&gt; /&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;注意，红色的部分一定不要去更改，否则就是无法成功。没有什么理由，但我也为此耗费了几个小时。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4. 重新调试客户端&lt;/p&gt;&#xD;
&lt;p&gt;客户端的配置和代码无需任何更改&lt;/p&gt;&#xD;
&lt;p&gt;如果正确地提供了密码，则会返回&amp;rdquo;Hello,world&amp;rdquo;，否则，会返回下面的错误&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_139.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" src="http://images.cnblogs.com/cnblogs_com/chenxizhang/WindowsLiveWriter/VS2008WSE3.0_10470/image_thumb.png" border="0" alt="image" width="470" height="279" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;应该用try&amp;hellip;catch的方式，捕捉到该异常之后，通知用户检查用户名和密码&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1887032.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1887032.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1885871.html</id><title type="text">Code-First Development with Entity Framework 4</title><summary type="text">.NET 4 ships with a much improved version of Entity Framework (EF) &amp;ndash; a data access library that lives in the System.Data.Entity namespace.When Entity Framework was first introduced with .NET 3.5...</summary><published>2010-11-23T12:45:00Z</published><updated>2010-11-23T12:45:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1885871.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1885871.html"/><content type="html">&lt;p&gt;&lt;span style="font-family: arial; font-size: 10pt;"&gt;&#xD;
&lt;p&gt;.NET 4 ships with a much improved version of Entity Framework (EF) &amp;ndash; a data access library that lives in the System.Data.Entity namespace.&lt;/p&gt;&#xD;
&lt;p&gt;When Entity Framework was first introduced with .NET 3.5 SP1, developers provided a lot of feedback on things they thought were incomplete with that first release.&amp;nbsp; The SQL team did a good job of listening to this feedback, and really focused the EF that ships with .NET 4 on addressing it.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;Some of the big improvements in EF4 include:&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;strong&gt;POCO Support:&lt;/strong&gt; You can now define entities without requiring base classes or data persistence attributes. &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Lazy Loading Support:&lt;/strong&gt; You can now load sub-objects of a model on demand instead of loading them up front. &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;N-Tier Support and Self-Tracking Entities:&lt;/strong&gt; Handle scenarios where entities flow across tiers or stateless web calls. &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Better SQL Generation and SPROC support&lt;/strong&gt;: EF4 executes better SQL, and includes better integration with SPROCs&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Automatic Pluralization Support&lt;/strong&gt;: EF4 includes automatic pluralization support of tables (e.g. Categories-&amp;gt;Category). &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Improved Testability&lt;/strong&gt;: EF4&amp;rsquo;s object context can now be more easily faked using interfaces. &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;Improved LINQ Operator Support&lt;/strong&gt;: EF4 now offers full support for LINQ operators. &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;Visual Studio 2010 also includes much richer EF designer and tooling support. The EF designer in VS 2010 supports both a &amp;ldquo;database first&amp;rdquo; development style &amp;ndash; where you construct your model layer on a design surface from an existing database.&amp;nbsp; It also supports a &amp;ldquo;model first&amp;rdquo; development style &amp;ndash; where you first define your model layer using the design surface, and can then use it to generate database schema from it.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Code-First Development with EF&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;In addition to supporting a designer-based development workflow, EF4 also enables a more &lt;em&gt;code-centric&lt;/em&gt; option which we call &amp;ldquo;code first development&amp;rdquo;.&amp;nbsp; Code-First Development enables a pretty sweet development workflow.&amp;nbsp; It enables you to:&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;Develop without ever having to open a designer or define an XML mapping file &lt;/li&gt;&#xD;
&lt;li&gt;Define your model objects by simply writing &amp;ldquo;plain old classes&amp;rdquo; with no base classes required &lt;/li&gt;&#xD;
&lt;li&gt;Use a &amp;ldquo;convention over configuration&amp;rdquo; approach that enables database persistence without explicitly configuring anything &lt;/li&gt;&#xD;
&lt;li&gt;Optionally override the convention-based persistence and use a fluent code API to fully customize the persistence mapping&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;EF&amp;rsquo;s &amp;ldquo;code first development&amp;rdquo; support is currently enabled with a separate download that runs on top of the core EF built-into .NET 4.&amp;nbsp; CTP4 of this &amp;ldquo;code-first&amp;rdquo; library &lt;a href="http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4announcement.aspx" target="_blank"&gt;shipped this week&lt;/a&gt; and can be downloaded &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4e094902-aeff-4ee2-a12d-5881d4b0dd3e&amp;amp;displaylang=en" target="_blank"&gt;here&lt;/a&gt;.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;It works with VS 2010, and you can use it with any .NET 4 project (including both ASP.NET Web Forms and ASP.NET MVC).&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step by Step Tutorial: Building NerdDinner using a Code-First Approach&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Last year I wrote an ASP.NET MVC 1.0 tutorial that was published both &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx" target="_blank"&gt;online&lt;/a&gt; and in a book.&amp;nbsp; The tutorial walked through creating a simple application, called &amp;ldquo;NerdDinner&amp;rdquo;, which provides an easy way for people to organize, host and RSVP for dinners online.&amp;nbsp; You can read my original ASP.NET V1 NerdDinner tutorial &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx" target="_blank"&gt;here&lt;/a&gt;.&amp;nbsp; An updated version of the tutorial is also included in the new &lt;a href="http://www.amazon.com/gp/product/0470643188?ie=UTF8&amp;amp;tag=scoblo04-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0470643188" target="_blank"&gt;Professional ASP.NET MVC 2&lt;/a&gt; book.&lt;/p&gt;&#xD;
&lt;p&gt;The NerdDinner tutorial used a &amp;ldquo;database first approach&amp;rdquo; where the database schema was defined first, and then we used a Visual Studio designer to create our LINQ to SQL / LINQ to Entities model objects that mapped to it.&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;Below I&amp;rsquo;m going to demonstrate how we could instead use a &amp;ldquo;code first approach&amp;rdquo; using EF4 to build the NerdDinner model layer and database schema, and construct a CRUD application using ASP.NET MVC.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_49970184.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_3A8022AA.png" border="0" alt="image" width="777" height="460" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We will walkthrough building this application step-by-step.&amp;nbsp; A download link to a completed version of the sample is available at the end of this blog post.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 1: Create a New Empty ASP.NET MVC 2 Application&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll start by creating a new ASP.NET MVC 2 Project within Visual Studio 2010.&amp;nbsp; Choose File-&amp;gt;New Project and use the &amp;ldquo;ASP.NET MVC 2 Empty Web Application&amp;rdquo; project template to do this.&lt;/p&gt;&#xD;
&lt;p&gt;This will create an empty ASP.NET MVC 2 project that does not have any controllers, models or views within it:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5A4F480C.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6D8FFEAB.png" border="0" alt="image" width="211" height="284" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll next work to define our NerdDinner &amp;ldquo;model&amp;rdquo; &amp;ndash; which refers to the objects that represent the data of our application, as well as the corresponding domain logic that integrates validation and business rules with it.&amp;nbsp; The model is the "heart" of an MVC-based application, and fundamentally drives the behavior of it.&amp;nbsp; We&amp;rsquo;ll create this model layer using the new EF4 &amp;ldquo;Code First&amp;rdquo; capabilities.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 2: Create our Model &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s assume we do not already have a database defined, and that we are building our new NerdDinner application completely from scratch.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;We do not need to start with a database&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;When using a code-first development workflow, we &lt;span style="text-decoration: underline;"&gt;do not&lt;/span&gt; need to begin our application by creating a database or specifying schema.&amp;nbsp; Instead we can begin by writing standard .NET classes that define the domain model objects that are most appropriate for our application &amp;ndash; without having to worry about intermixing data persistence logic within them.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Creating Model Classes&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;NerdDinner is a small application, and our data storage needs with it are pretty simple.&amp;nbsp; We want to be able to define and store &amp;ldquo;Dinners&amp;rdquo; that refer to specific events that people can attend.&amp;nbsp; We also want to be able to define and store &amp;ldquo;RSVP&amp;rdquo; acceptances, which are used to track a person&amp;rsquo;s interest in attending a particular Dinner.&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s create two classes (Dinner and RSVP) to represent these concepts.&amp;nbsp; We&amp;rsquo;ll do this by adding two new classes to our ASP.NET MVC project - &amp;ldquo;Dinner&amp;rdquo; and &amp;ldquo;RSVP&amp;rdquo;:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_25CE75C4.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_24F60FDA.png" border="0" alt="image" width="519" height="392" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The above &amp;ldquo;Dinner&amp;rdquo; and &amp;ldquo;RSVP&amp;rdquo; model classes are &amp;ldquo;plain old CLR objects&amp;rdquo; (aka POCO).&amp;nbsp; They &lt;span style="text-decoration: underline;"&gt;do not&lt;/span&gt; need to derive from any base classes or implement any interfaces, and the properties they expose are standard .NET data-types.&amp;nbsp; No data persistence attributes or data code has been added to them.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;The ability to define model classes without having to tie them to a particular database, database API, or database schema implementation is really powerful &amp;ndash; and provides us with much more data access flexibility.&amp;nbsp; It allows us to focus on our application/business needs without having to worry about persistence implementation.&amp;nbsp; It also gives us the flexibility to change our database schema or storage implementation in the future &amp;ndash; without having to re-write our model objects, or the code that interacts with them.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Creating a Context Class to Handle Database Persistence&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Now that we&amp;rsquo;ve defined our two POCO model classes, let&amp;rsquo;s create a class that we can use to handle the retrieval/persistence of Dinner and RSVP instances from a database.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll name this class &amp;ldquo;NerdDinners&amp;rdquo;. It derives from the DbContext base class, and publishes two public properties &amp;ndash; one that exposes our Dinner objects, and one that exposes our RSVP objects:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_241DA9F0.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_1C923A83.png" border="0" alt="image" width="429" height="124" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The DbContext and DbSet classes used above are provided as part of the EF4 Code-First library.&amp;nbsp; You&amp;rsquo;ll need to add a reference to the System.Data.Entity.CTP assembly that is installed into the &lt;em&gt;\Program Files\Microsoft ADO.NET Entity Framework Feature CTP4\Binaries&lt;/em&gt; directory to reference these classes.&amp;nbsp; You&amp;rsquo;ll also want to add a &amp;ldquo;using System.Data.Entity&amp;rdquo; namespace statement at the top of your &amp;ldquo;NerdDinners&amp;rdquo; class file.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;That is all the code we need to write&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The above three classes contain &lt;span style="text-decoration: underline;"&gt;all of the code&lt;/span&gt; necessary to implement a basic model and data persistence layer for our NerdDinner application.&amp;nbsp; We &lt;span style="text-decoration: underline;"&gt;do not&lt;/span&gt; need to configure any additional database schema mapping information, nor run any tools, nor edit any XML files, nor use any designers in order to start using our classes to retrieve, update, and save data into a database. &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Convention Based Persistence Mapping&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We do not need to write any additional code, nor create any XML files, nor use any tools in order to map our model classes to and from a database.&amp;nbsp; How, you might ask, is that possible?&lt;/p&gt;&#xD;
&lt;p&gt;By default, EF code-first supports a &amp;ldquo;convention over configuration&amp;rdquo; approach that enables you to rely on common mapping conventions instead of having to explicitly configure things.&amp;nbsp; You &lt;em&gt;can&lt;/em&gt; override these conventions if you want to provide custom database mapping rules.&amp;nbsp; But if you instead just use the default conventions you&amp;rsquo;ll find that the amount of code you have to write is really small, and the common 90% of scenarios &amp;ldquo;just work&amp;rdquo; the way you&amp;rsquo;d expect them to without any extra code or configuration.&lt;/p&gt;&#xD;
&lt;p&gt;In our example above, our NerdDinners context class will by default map its &amp;ldquo;Dinners&amp;rdquo; and &amp;ldquo;RSVPs&amp;rdquo; properties to &amp;ldquo;Dinners&amp;rdquo; and &amp;ldquo;RSVPs&amp;rdquo; tables within a database.&amp;nbsp; Each row within the Dinners table will map to an instance of our &amp;ldquo;Dinner&amp;rdquo; class.&amp;nbsp; Likewise, each row within the RSVPs table will map to an instance of our &amp;ldquo;RSVP&amp;rdquo; class.&amp;nbsp; Properties within the &amp;ldquo;Dinner&amp;rdquo; and &amp;ldquo;RSVP&amp;rdquo; classes in turn map to columns within the respective &amp;ldquo;Dinners&amp;rdquo; and &amp;ldquo;RSVPs&amp;rdquo; database tables.&lt;/p&gt;&#xD;
&lt;p&gt;Other default conventions supported by EF include the ability to automatically identify primary-key and foreign keys based on common naming patterns (for example: an ID or DinnerID property on the Dinner class will be inferred as the primary key).&amp;nbsp; EF also includes smart conventions for wiring-up association relationships between models.&amp;nbsp; The EF team has a blog post that talks more about how the default set of conventions work &lt;a href="http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Code Examples of How to Use Our Model&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The three classes we created earlier contain &lt;span style="text-decoration: underline;"&gt;all of the code&lt;/span&gt; necessary to implement our model and data persistence for NerdDinner.&amp;nbsp; Let&amp;rsquo;s now look at a few code examples of how we can use these classes to perform common data scenarios:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Query Using LINQ Expressions&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We can write LINQ query expressions to retrieve data from a database using the following code.&amp;nbsp; Below we are using a LINQ expression to retrieve all dinners that occur in the future:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_1506CB16.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_54647EA6.png" border="0" alt="image" width="424" height="165" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We can also take advantage of relationships between Dinners and RSVPs when writing our LINQ expressions.&amp;nbsp; Notice below how our &amp;ldquo;where&amp;rdquo; statement filters by dinners whose RSVP count is greater than 0:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_41AF84EF.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_3A241582.png" border="0" alt="image" width="447" height="171" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Note that the &amp;ldquo;where&amp;rdquo; filter in the above query (where we are retrieving only those Dinners who have at least one RSVP) executes in the database server &amp;ndash; making the query and the amount of data we retrieve very efficient.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Retrieving a Single Instance&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We can use LINQ&amp;rsquo;s Single() method with a lambda query to retrieve a single instance of a Dinner using code like below:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6085F8CD.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_58FA8960.png" border="0" alt="image" width="552" height="132" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Alternatively, we can also take advantage of a Find() method that EF &amp;ldquo;code-first&amp;rdquo; exposes that allows you to easily retrieve an instance based on its ID:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_144DEF1F.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0CC27FB2.png" border="0" alt="image" width="426" height="128" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Adding a new Dinner&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The code below demonstrates how to create and add a new Dinner to the database.&amp;nbsp; All we need to do is to &amp;ldquo;new&amp;rdquo; a Dinner object, set properties on it, and then add it to the Dinners property of our NerdDinners context object.&amp;nbsp; The NerdDinner context class supports a &amp;ldquo;unit of work&amp;rdquo; pattern that enables you to add multiple models to the context, and then call &amp;ldquo;SaveChanges()&amp;rdquo; on it to persist all of the changes to a database as a single atomic transaction.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_05371045.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2479B718.png" border="0" alt="image" width="438" height="299" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Updating a Dinner&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The code below demonstrates how to retrieve a Dinner, update one of its properties, and then save the changes back to the database:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_2AC08DA6.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_512270F1.png" border="0" alt="image" width="408" height="187" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 3: Create a ASP.NET MVC Controller that uses our Model&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s now look at a more complete scenario involving our model, where we use a controller class to implement the functionality necessary to publish a list of upcoming dinners, and enable users to add new ones:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_49970184.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_3A8022AA.png" border="0" alt="image" width="777" height="460" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll implement this functionality by right-clicking on the &amp;ldquo;Controllers&amp;rdquo; folder and choose the &amp;ldquo;Add-&amp;gt;Controller&amp;rdquo; menu command.&amp;nbsp; We&amp;rsquo;ll name our new controller &amp;ldquo;HomeController&amp;rdquo;.&lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll then add three &amp;ldquo;action methods&amp;rdquo; within it that work with the NerdDinners model we created earlier using EF &amp;ldquo;Code-First&amp;rdquo;:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_52375A10.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_5F313A21.png" border="0" alt="image" width="500" height="811" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The &amp;ldquo;Index&amp;rdquo; action method above retrieves and renders a list of upcoming dinners.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;The &amp;ldquo;Create&amp;rdquo; action methods allow users to add new dinners.&amp;nbsp; The first &amp;ldquo;Create&amp;rdquo; method above handles the &amp;ldquo;HTTP GET&amp;rdquo; scenario when a user visits the /Home/Create URL, and send back a &amp;ldquo;New Dinner&amp;rdquo; form to fill out.&amp;nbsp; The second &amp;ldquo;Create&amp;rdquo; method handles the &amp;ldquo;HTTP POST&amp;rdquo; scenario associated with the form &amp;ndash; and handles saving the dinner in the database.&amp;nbsp; If there are any validation issues it redisplays the form back to the user with appropriate error messages.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Adding Views for our Controllers&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Our next step will be to add two &amp;ldquo;View templates&amp;rdquo; to our project &amp;ndash; one for &amp;ldquo;Index&amp;rdquo; and one for &amp;ldquo;Create&amp;rdquo;.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll add the &amp;ldquo;Index&amp;rdquo; view to our project by moving our cursor within the Index action method of our controller, and then right-click and choose the &amp;ldquo;Add View&amp;rdquo; menu command.&amp;nbsp; This will bring up the &amp;ldquo;Add View&amp;rdquo; dialog.&amp;nbsp; We&amp;rsquo;ll specify that we want to create a strongly-typed view, and that we are passing in a IEnumerable list of &amp;ldquo;Dinner&amp;rdquo; model objects to it:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_306B817F.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2F931B95.png" border="0" alt="image" width="443" height="437" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;When we click &amp;ldquo;Add&amp;rdquo;, Visual Studio will create a /&lt;em&gt;Views/Home/Index.aspx&lt;/em&gt; file.&amp;nbsp; Let&amp;rsquo;s then add the following code to it &amp;ndash; which generates a &amp;lt;ul&amp;gt; list of Dinners, and renders a hyperlink that links to our create action:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_0A955B1C.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7BEAAF36.png" border="0" alt="image" width="523" height="321" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ll then add the &amp;ldquo;Create&amp;rdquo; view to our project by moving our cursor within the Create action method of our controller, and then right-click and choose the &amp;ldquo;Add View&amp;rdquo; menu command.&amp;nbsp; Within the &amp;ldquo;Add View&amp;rdquo; dialog we&amp;rsquo;ll specify that we want to create a strongly-typed view, and that we are passing it a Dinner object.&amp;nbsp; We&amp;rsquo;ll also indicate that we want to &amp;ldquo;scaffold&amp;rdquo; using a &amp;ldquo;Create&amp;rdquo; template:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_023185C5.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6C679D67.png" border="0" alt="image" width="443" height="437" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;When we click &amp;ldquo;Add&amp;rdquo;, Visual Studio will create a &lt;em&gt;/Views/Home/Create.aspx&lt;/em&gt; file with some scaffold-generated content within it that outputs an HTML &amp;lt;form&amp;gt; for a &amp;ldquo;Dinner&amp;rdquo; object.&amp;nbsp; We&amp;rsquo;ll tweak it slightly and remove the input element for the DinnerID property.&amp;nbsp; Our final view template content will look like this:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6B8F377D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7169DB16.png" border="0" alt="image" width="640" height="884" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We have now implemented all of the code we need to write within our Controller and Views to implement the Dinner listing and Dinner creation functionality within our web application.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 4: The Database&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ve written our code.&amp;nbsp; Now let&amp;rsquo;s run the application.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;But what about the database?&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We don&amp;rsquo;t have a database yet &amp;ndash; and haven&amp;rsquo;t needed one so far because our &amp;ldquo;code first&amp;rdquo; development workflow hasn&amp;rsquo;t required us to have one to define and use our model classes.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;But we will need a database when we actually run our application and want to store our Dinner and RSVP objects.&amp;nbsp; We can create the database one of two ways:&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
&lt;li&gt;Manually create and define the schema ourselves using a database tool (e.g. SQL Management Studio or Visual Studio) &lt;/li&gt;&#xD;
&lt;li&gt;Automatically create and generate the schema directly from our model classes using the EF Code-First library &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p&gt;This second option is pretty cool and is what we are going to use for our NerdDinner application.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Configuring our Database Connection String&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;To begin with, we&amp;rsquo;ll setup a connection-string to point to where we want our database to live.&amp;nbsp; We&amp;rsquo;ll do this by adding a &amp;ldquo;NerdDinners&amp;rdquo; connection-string entry to our application&amp;rsquo;s web.config file like so:&amp;nbsp; &lt;/p&gt;&#xD;
&lt;pre&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5076686F.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6FB90F42.png" border="0" alt="image" width="599" height="158" /&gt;&lt;/a&gt; &lt;/pre&gt;&#xD;
&lt;p&gt;By default, when you create a DbContext class with EF code-first, it will look for a connection-string that matches the name of the context-class.&amp;nbsp; Since we named our context class &amp;ldquo;NerdDinners&amp;rdquo;, it will by default look for and use the above &amp;ldquo;NerdDinners&amp;rdquo; database connection-string when it is instantiated within our ASP.NET application. &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Taking advantage of SQL CE 4&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;You can use many different databases with EF code-first &amp;ndash; including SQL Server, SQL Express and MySQL.&lt;/p&gt;&#xD;
&lt;p&gt;Two weeks ago &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/06/30/new-embedded-database-support-with-asp-net.aspx" target="_blank"&gt;I blogged&lt;/a&gt; about the work we are also doing to enable the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/06/30/new-embedded-database-support-with-asp-net.aspx" target="_blank"&gt;embedded SQL CE 4 database engine&lt;/a&gt; to work within ASP.NET.&amp;nbsp; SQL CE 4 is a lightweight file-based database that is free, simple to setup, and can be embedded within your ASP.NET applications.&amp;nbsp; It supports low-cost hosting environments, and enables databases to be easily migrated to SQL Server.&lt;/p&gt;&#xD;
&lt;p&gt;SQL CE can be a useful option to use when you are in the early stages of defining (and redefining) your model layer &amp;ndash; and want to be able to quickly create and recreate your database as you do so.&amp;nbsp; We&amp;rsquo;ll use SQL CE 4 to begin with as we develop our NerdDinner application.&amp;nbsp; We can later optionally change the connection-string to use SQL Express or SQL Server for production deployment &amp;ndash; without having to modify a single line of code within our application.&lt;/p&gt;&#xD;
&lt;p&gt;The connection-string I specified above points to a NerdDinners.sdf database file, and specifies the SQL CE 4 database provider.&amp;nbsp; In order for this to work you need to install SQL CE 4 &amp;ndash; either via the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en" target="_blank"&gt;Standalone SQL CE Installer&lt;/a&gt; or by installing &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx" target="_blank"&gt;WebMatrix&lt;/a&gt; (which includes it built-in).&amp;nbsp; SQL CE 4 is a small download that only takes a few seconds to install.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Important: &lt;/strong&gt;In the connection-string above I&amp;rsquo;m indicating that we want to create the NerdDinners.sdf file within the |DataDirectory| folder &amp;ndash; which in an ASP.NET application is the \App_Data\ folder immediately underneath the application directory.&amp;nbsp; By default the &amp;ldquo;Empty ASP.NET MVC Web Application&amp;rdquo; project template does not create this directory.&amp;nbsp; You will need to explicitly create this directory within your project (right click on the project and choose the &amp;ldquo;Add-&amp;gt;ASP.NET Folder-&amp;gt;Add_Data&amp;rdquo; menu item).&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Automatic Database Schema Creation&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;EF code-first supports the ability to automatically generate database schema and create databases from model classes &amp;ndash; enabling you to avoid having to manually perform these steps.&lt;/p&gt;&#xD;
&lt;p&gt;This happens &lt;span style="text-decoration: underline;"&gt;by default&lt;/span&gt; if your connection-string points to either a SQL CE or SQL Express database file that &lt;span style="text-decoration: underline;"&gt;does not already exist on disk&lt;/span&gt;.&amp;nbsp; You do not need to take any manual steps for this to happen.&lt;/p&gt;&#xD;
&lt;p&gt;To see this in action, we can press F5 to run our NerdDinner application.&amp;nbsp; This will launch a browser at the root &amp;ldquo;/&amp;rdquo; URL of our application.&amp;nbsp; You should see a screen like below rendered back:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6EE0A958.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_46CDFA39.png" border="0" alt="image" width="575" height="373" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The &amp;ldquo;/&amp;rdquo; URL to our application invoked the HomeController.Index() action method &amp;ndash; which instantiated and queried our NerdDinners context object to retrieve all upcoming Dinners from our database.&amp;nbsp; Because the NerdDinners.sdf database file we pointed our connection-string to didn&amp;rsquo;t already exist, the EF code-first library automatically generated it for us.&amp;nbsp; It used our NerdDinners context object to automatically infer the database schema for the database it generated.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;To see the SQL CE database file that was generated, click the &amp;ldquo;Show all Files&amp;rdquo; icon within the Visual Studio solution explorer, and then press the &amp;ldquo;Refresh&amp;rdquo; button and expand the App_Data folder: &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_33ACCD8D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0B9A1E6E.png" border="0" alt="image" width="199" height="344" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;We will be shipping an update to VS 2010 in the future that enables you to open up and edit SQL CE 4 databases within the &amp;ldquo;Server Explorer&amp;rdquo; tab (just like you do with SQL databases today).&amp;nbsp; This will enable you to easily see (and optionally tweak) the schema and contents of the database.&amp;nbsp; Until then you can optionally use the database tools within WebMatrix to examine the SQL CE 4 database file&amp;rsquo;s contents.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;We did not specify any custom persistence mapping rules with our NerdDinners context &amp;ndash; so the database that was generated followed the default EF code-first naming conventions to map the schema.&amp;nbsp; If we had specified any custom mapping rules, though, the EF code-first library would have honored those and generated a database that matched them.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;Just to refresh our memory &amp;ndash; here are the two POCO model classes and the NerdDinners context class that we defined earlier:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_38AF0B3C.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_30B768DA.png" border="0" alt="image" width="509" height="513" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Below are the tables that were added when we ran our application and the database was automatically created based on the above model:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_2FDF02F0.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_0F57C33E.png" border="0" alt="image" width="170" height="112" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;The definition of the &amp;ldquo;Dinners&amp;rdquo; table looks like below.&amp;nbsp; The column names and data-types map to the properties of the Dinner class we defined.&amp;nbsp; The DinnerID column has also been configured to be both a primary key and an identity column:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_3CD8E301.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_54FC4D5C.png" border="0" alt="image" width="336" height="314" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The definition of the &amp;ldquo;RSVPs&amp;rdquo; table looks like below.&amp;nbsp; The column names and data-types map to the properties of the RSVP class we defined.&amp;nbsp; The RsvpID column has also been configured to be both a primary key and an identity column:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5B4323EA.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_6594484A.png" border="0" alt="image" width="334" height="303" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;A one to many primary key/foreign key relationship was also established between the Dinners and RSVPs tables.&amp;nbsp; The EF code-first library inferred that this should be established because our Dinner class has an ICollection&amp;lt;RSVP&amp;gt; property named RSVPs, and the RSVP class has a Dinner property.&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Populating the Database with some Dinners&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s now create and add some Dinners to our database.&amp;nbsp; We&amp;rsquo;ll do this by clicking the &amp;ldquo;Create New Dinner&amp;rdquo; link on our home-page to navigate to our &amp;ldquo;Create&amp;rdquo; form:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6BDB1ED8.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_71B5C271.png" border="0" alt="image" width="569" height="488" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;When we click the &amp;ldquo;Create&amp;rdquo; button, our new Dinner will be saved in the database.&amp;nbsp; We can repeat this multiple times to register several different Dinners.&amp;nbsp; Each new Dinner we create will be persisted within our database and show up in our Home listing of upcoming dinners:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_02B9F055.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7AC24DF2.png" border="0" alt="image" width="578" height="356" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 5: Changing our Model&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We are going to continually evolve and refactor our model as our application grows.&amp;nbsp; The EF code-only library includes some nice development features that make it easier to coordinate this evolution with a development database.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Adding a new Property to the Dinner Model&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s walkthrough making a simple change to our Dinner class.&amp;nbsp; Specifically, we&amp;rsquo;ll add an additional property to our Dinner class called &amp;ldquo;Country&amp;rdquo;:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_55C48D79.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7507344C.png" border="0" alt="image" width="505" height="237" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Now that we&amp;rsquo;ve made this change, let&amp;rsquo;s press F5 in Visual Studio to build and re-run the application.&amp;nbsp; When we do this we&amp;rsquo;ll see the below error message:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_665C8867.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_5DF8B310.png" border="0" alt="image" width="663" height="406" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;This error message occurs because we&amp;rsquo;ve changed the structure of our Dinner class, and our model object is now no longer the same shape as the &amp;ldquo;Dinners&amp;rdquo; table we automatically created within our database.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;When EF automatically creates a database for you, it by default adds an &amp;ldquo;EdmMetadata&amp;rdquo; table to the database that tracks the shape of the model objects that were used to automatically create the database schema for you:&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6AF29321.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_5594DDB9.png" border="0" alt="image" width="180" height="108" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The error message above occurs when EF detects that you&amp;rsquo;ve made a change to a model object and it is now out of sync with the database it automatically created for you.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Re-synchronizing our Model Classes with the Database&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;There are a couple of ways we can &amp;ldquo;re-sync&amp;rdquo; our model objects and our database:&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;We can manually update our database schema to match our models &lt;/li&gt;&#xD;
&lt;li&gt;We can manually delete our database file, re-run the application, and have EF automatically re-create the database &lt;/li&gt;&#xD;
&lt;li&gt;We can enable a feature of EF code-first that automatically updates our database for us whenever we change our models &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s look at how we can use this last automatic option with our NerdDinner application.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;The RecreateDatabaseIfModelChanges Feature&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;CTP 4 of the EF Code First library includes a useful &lt;span style="text-decoration: underline;"&gt;&lt;em&gt;development-time&lt;/em&gt;&lt;/span&gt; feature that enables you to automatically re-create your database anytime you make modifications to your model classes.&amp;nbsp; When you enable it, EF identifies when any of the model classes that were used to automatically create a database are modified, and when that happens can re-create your database to match the new model class shape &amp;ndash; &lt;span style="text-decoration: underline;"&gt;without you having to take any manual steps to do so&lt;/span&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;This capability is especially useful when you are first developing an application, since it gives you the freedom and flexibility to quickly refactor and restructure your model code however you want - without having to do any manual work to keep your database schema in sync along the way.&amp;nbsp; It works especially well with SQL CE &amp;ndash; since it is a file-based database that can be dropped and recreated on the fly in under a second.&amp;nbsp; This can enable an incredibly fluid development workflow.&lt;/p&gt;&#xD;
&lt;p&gt;The easiest way to enable this capability is to add a Database.SetInitializer() call to the Application_Start() event handler within our Global.asax class:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_0315FD7D.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_1B3967D8.png" border="0" alt="image" width="794" height="144" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;This tells EF to re-create our NerdDinners.sdf database to match our NerdDinners model anytime our model classes change shape.&amp;nbsp; Now when we re-run our application we will no longer get that error message telling us that our model classes and database are out of sync.&amp;nbsp; EF will instead automatically re-create a database for us that matches our new model class shape, and our application will run fine:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_6F889DDB.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_39A3A8C1.png" border="0" alt="image" width="547" height="295" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Seeding Initial Data in Automatically Created Databases&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;One of the things you might have noticed in the above screen-shot is that we lost our dinner data when we recreated the database.&amp;nbsp; This is because the automatic &amp;ldquo;RecreateDatabaseIfModelChanges&amp;rdquo; behavior isn&amp;rsquo;t intended for production scenarios where you want to &amp;ldquo;migrate&amp;rdquo; existing data from one schema to another.&amp;nbsp; Instead it is designed for development scenarios where you want the database to be quickly and automatically updated for you &amp;ndash; without you having to take any manual steps or specify migration rules to do so.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;em&gt;Note: We are separately working to provide better data migration support for scenarios where you are working with production data and want to version the schema.&amp;nbsp; We think of that as a different scenario than this early development-time feature that I&amp;rsquo;m describing here.&amp;nbsp; The data migration capability isn&amp;rsquo;t enabled yet with this week&amp;rsquo;s CTP.&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;/blockquote&gt;&#xD;
&lt;p&gt;EF supports the ability for us to optionally &amp;ldquo;seed&amp;rdquo; our generated database with default/test data anytime the database is created/recreated.&amp;nbsp; I find this feature really useful since it enables me to refactor a model, and then quickly run the application to try out a scenario &amp;ndash; without having to enter in a bunch of test data manually to do so.&lt;/p&gt;&#xD;
&lt;p&gt;We can &amp;ldquo;seed&amp;rdquo; our NerdDinners database with default data by writing a &amp;ldquo;NerdDinnersIntializer&amp;rdquo; class like below.&amp;nbsp; I&amp;rsquo;m using it to create two &amp;ldquo;sample dinners&amp;rdquo; and adding them to our database like so:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_18B0361A.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_57A1B6B5.png" border="0" alt="image" width="692" height="481" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;We can then update the Database.Initializer() call we added to our Global.asax to use this &amp;ldquo;NerdDinnersInitializer&amp;rdquo; class at startup:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_04B6A384.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_1627045C.png" border="0" alt="image" width="623" height="144" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;And now anytime we make a change to one of our NerdDinner model classes, the database will be automatically dropped and recreated to match our models, and we&amp;rsquo;ll have two dinners already seeded in the database for testing purposes:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_3C88E7A7.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_3BB081BD.png" border="0" alt="image" width="586" height="328" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Easy Refactoring&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The above features make it really easy to evolve and refactor your code at development time &amp;ndash; without having to use tools or run scripts to manually keep your database in sync with your code changes.&lt;/p&gt;&#xD;
&lt;p&gt;Because our model classes, LINQ expressions, and &amp;ldquo;seed&amp;rdquo; test data are all strongly typed, we can also take advantage of refactoring tool support inside Visual Studio to quickly and automatically apply changes across our code base in a quick and easy way.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Step 6: Adding Validation Rules&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;We&amp;rsquo;ve built a nice, simple data-entry application.&lt;/p&gt;&#xD;
&lt;p&gt;One problem with it, though, is that we don&amp;rsquo;t currently have any type of input validation in place to ensure that fields are filled out correctly within our Create Dinner form.&amp;nbsp; Let&amp;rsquo;s fix that.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Adding Validation using DataAnnotations&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Validation rules in an ASP.NET MVC based application are usually best expressed within a model.&amp;nbsp; This enables them to be maintained in a single place, and enforced across any number of controllers and views that might interact with them.&amp;nbsp; ASP.NET MVC enables you to implement validation rules using a variety of different mechanisms, and is flexible enough to support just about any validation scheme you want to use.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;ASP.NET MVC 2 includes built-in support for using .NET&amp;rsquo;s &lt;em&gt;System.ComponentModel.DataAnnotations&lt;/em&gt; library of validation rules &amp;ndash; which enable you to declaratively apply validation rules to model classes using validation attributes.&amp;nbsp; You can learn more about this capability in a &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx" target="_blank"&gt;previous blog post I wrote&lt;/a&gt;.&amp;nbsp; We&amp;rsquo;ll take advantage of this approach to enable input validation for our NerdDinner application.&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s go back to the Dinner class we defined earlier and add some validation attributes to its properties (note: we need to add a &amp;ldquo;using System.ComponentModel.DataAnnotations&amp;rdquo; namespace as well):&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_1ABD0F16.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2097B2AF.png" border="0" alt="image" width="785" height="432" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;The [Required] validation attribute indicates that a particular property must be specified.&amp;nbsp; The [StringLength] validation attribute allows us to indicate a maximum length for a particular string property.&amp;nbsp; The [RegularExpression] validation attribute allows us to indicate that a particular string property must match a specified regular expression in order to be valid &amp;ndash; in this case an email address.&lt;/p&gt;&#xD;
&lt;p&gt;Each of the validation attributes supports an &amp;ldquo;ErrorMessage&amp;rdquo; property &amp;ndash; which allows us to specify an error message that should be displayed if the validation fails.&amp;nbsp; This can either be hard-coded as a string (like above) or pulled from a resource &amp;ndash; enabling it to be easily localized.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Referencing some CSS and JavaScript files&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;The last step will be to go back to our Create.aspx view template and add a &amp;lt;link&amp;gt; reference to a Site.css file in our project, as well as two &amp;lt;script&amp;gt; elements that reference two JavaScript files in our project.&amp;nbsp; We&amp;rsquo;ll also add one line of code to call Html.EnableClientValidation() before our &amp;lt;form&amp;gt; element is rendered:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_71D1FA0C.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_057EE3A1.png" border="0" alt="image" width="709" height="207" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;These changes will ensure that any validation error messages that are displayed in the page are styled (to make them more visible), and that the validation rules we apply on our model will be applied both on the client and on the server.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;Running the Application&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Let&amp;rsquo;s re-run the application and try to create a new Dinner.&amp;nbsp; Let&amp;rsquo;s begin by pushing the &amp;ldquo;Create&amp;rdquo; button with no values filled out.&amp;nbsp; We&amp;rsquo;ll find that we now see the validation error messages we applied to our model showing up in the browser:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_76D437BB.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2EA67BDF.png" border="0" alt="image" width="585" height="495" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Because we enabled client-side validation with ASP.NET MVC (that was the one line of code we wrote above), our error messages will update and change in real-time:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_549C2C35.png"&gt;&lt;img style="border-width: 0px; display: inline;" title="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_7372A013.png" border="0" alt="image" width="585" height="495" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;Notice above how our validation error message changed once our &amp;ldquo;Title&amp;rdquo; became longer than 20 characters.&amp;nbsp; This is because we have a [StringLength] property on our Dinner.Title property that indicates a maximum allowed size of 20 characters.&amp;nbsp; As we started entering a value within the &amp;ldquo;HostedBy&amp;rdquo; textbox, our error message likewise changed from the &amp;ldquo;[Requred]&amp;rdquo; error message (which asks you to enter your email address) to the &amp;ldquo;[RegularExpression]&amp;rdquo; error message (which is telling us we don&amp;rsquo;t have a valid email address).&lt;/p&gt;&#xD;
&lt;p&gt;These validation rules work both within the browser (via JavaScript) and on the server (enabling us to protect ourselves even if someone tries to bypass the JavaScript validation) &amp;ndash; without us having to make any changes to our controller class.&amp;nbsp; The ability to specify these rules once within our model, and have them apply everywhere, is extremely powerful &amp;ndash; and will enable us to continue to evolve our application in a very clean way.&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;You can learn more about these ASP.NET MVC 2 Model Validation features and how they work &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Download&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.scottgu.com/blogposts/nerddinnerreloaded.zip" target="_blank"&gt;Click here&lt;/a&gt; to download and run the above NerdDinnerReloaded sample we&amp;rsquo;ve built in this blog post.&amp;nbsp; It requires VS 2010 (or the free Visual Web Developer 2010 Express).&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: You must &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en" target="_blank"&gt;download and install SQL CE 4&lt;/a&gt; on your machine for the above sample to work.&amp;nbsp; You can download the EF Code-First library &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4e094902-aeff-4ee2-a12d-5881d4b0dd3e&amp;amp;displaylang=en" target="_blank"&gt;here&lt;/a&gt;.&amp;nbsp; Neither of these downloads will impact your machine.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Summary&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;This week&amp;rsquo;s CTP4 release of the &amp;ldquo;EF Code-First&amp;rdquo; functionality provides a pretty nice code-centric way to work with data.&amp;nbsp; It brings with it a lot of productivity, as well as a lot of power.&amp;nbsp; In today&amp;rsquo;s tutorial I focused mostly on some of the new productivity enhancements provided with the CTP4 release.&amp;nbsp; There are many more scenarios we could drill into including its Fluent API for enabling custom persistence mapping rules, its improved testability support, and other more advanced capabilities.&lt;/p&gt;&#xD;
&lt;p&gt;You can download this week&amp;rsquo;s CTP4 release of EF Code-First &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=4e094902-aeff-4ee2-a12d-5881d4b0dd3e&amp;amp;displaylang=en" target="_blank"&gt;here&lt;/a&gt;.&amp;nbsp; To learn even more about &amp;ldquo;EF Code-First&amp;rdquo; check out these blog posts by the ADO.NET team:&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4announcement.aspx" target="_blank"&gt;EF CTP4 Announcement Blog Post&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4piwalkthrough.aspx" target="_blank"&gt;EF CTP4 Productivity Enhancements Blog Post&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4codefirstwalkthrough.aspx" target="_blank"&gt;EF CTP4 Code First Walkthrough Blog Post&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx" target="_blank"&gt;DataAnnotations and Code First&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx" target="_blank"&gt;Default conventions with Code First&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx" target="_blank"&gt;Scott Hanselman&amp;rsquo;s Walkthrough Post about CTP4&lt;/a&gt; &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1885871.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1885871.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/h-hello/articles/1834727.html</id><title type="text">DD_belatedPNG,解决IE6不支持PNG绝佳方案</title><summary type="text">我们知道IE6是不支持透明的PNG的,这无疑限制了网页设计的发挥空间.然而整个互联网上解决这个IE6的透明PNG的方案也是多不胜数,从使用IE特有的滤镜或是e&amp;shy;xpression,再到javascript+透明GIF替代.但是这些方法都有一个缺点,就是不支持CSS中backgrond-position与background-repeat.而我今天介绍DD_belatedPNG,只需要一个理...</summary><published>2010-09-25T09:20:00Z</published><updated>2010-09-25T09:20:00Z</updated><author><name>h-hello</name><uri>http://www.cnblogs.com/h-hello/</uri></author><link rel="alternate" href="http://www.cnblogs.com/h-hello/articles/1834727.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/h-hello/articles/1834727.html"/><content type="html">&lt;p&gt;我们知道IE6是不支持透明的PNG的,这无疑限制了网页设计的发挥空间.&lt;br /&gt;然而整个互联网上解决这个IE6的透明PNG的方案也是多不胜数,从使用IE特有的滤镜或是e&amp;shy;xpression,再到javascript+透明GIF替代.但是这些方法都有一个&lt;strong&gt;缺点&lt;/strong&gt;,就是不支持CSS中&lt;strong&gt;backgrond-position&lt;/strong&gt;与&lt;strong&gt;background-repeat&lt;/strong&gt;.&lt;/p&gt;&#xD;
&lt;p&gt;而我今天介绍DD_belatedPNG,只需要&lt;strong&gt;一个理由&lt;/strong&gt;,就是它支持&lt;strong&gt;backgrond-position&lt;/strong&gt;与&lt;strong&gt;background-repeat&lt;/strong&gt;.这是其他js插件不具备的.同时DD_belatedPNG还支持a:hover属性,以及&amp;lt;img&amp;gt;.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.ediyang.com/demo/DD_Png/"&gt;看Demo&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个js插件使用了微软的VML语言进行绘制,而其他多数解决PNG问题的js插件用的是AlphaImageLoader滤镜.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;使用方法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1.在&lt;a href="http://dillerdesign.com/experiment/DD_belatedPNG/#download"&gt;这里&lt;/a&gt;下载DD_belatedPNG.js文件.&lt;br /&gt;2.在网页中引用,如下:&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;code&gt;&amp;lt;!--[if IE 6]&amp;gt;&amp;lt;script src="DD_belatedPNG.js" mce_src="DD_belatedPNG.js"&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script type="text/javascript"&amp;gt;&amp;lt;!&amp;lt;!/* EXAMPLE */DD_belatedPNG.fix('.png_bg');/* 将 .png_bg 改成你应用了透明PNG的CSS选择器,例如我例子中的'.trans'*/// --&amp;gt;&lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;3.有2种调用函数,一种是DD_belatedPNG.fix(),如上代码.另一种是fix(),这中方法需要在函数内指出css选择器名.&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;使用a:hover请留意&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5-25更新:&lt;/strong&gt;如果你也像&lt;a href="http://www.jutoy.net/"&gt;jutoy&lt;/a&gt;同学一样想要用透明PNG作为a:hover时的背景图片,那么你需要留意你的代码,&lt;strong&gt;需要以&amp;rdquo;a:hover&amp;rdquo;来作为选择器&lt;/strong&gt;.否则可能会导致无法成功.同时我也更新了demo,请需要的更新查看.接着我们看看&lt;strong&gt;正确&lt;/strong&gt;的代码:&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;code&gt;&amp;lt;!--[if IE 6]&amp;gt;&amp;lt;script type="text/javascript" src="js/DD_belatedPNG.js" &amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script type="text/javascript"&amp;gt;DD_belatedPNG.fix('.trans,.box a:hover');&amp;lt;/script&amp;gt;&amp;lt;![endif]--&amp;gt;&lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;&lt;strong&gt;其他方案&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在这里还是提供其他方案供大家参考.尽管我觉得DD_belatedPNG最好&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;a href="http://unitinteractive.com/labs/unitpngfix.php"&gt;Unit PNG Fix&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://unitinteractive.com/labs/unitpngfix.php"&gt;ie7-js&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;a href="http://www.twinhelix.com/css/iepngfix/"&gt;IE PNG Fix&lt;/a&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/h-hello/aggbug/1834727.html?type=2" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/h-hello/articles/1834727.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
