<?xml version="1.0" encoding="gb2312"?>

<!-- RSS generated by oioj.net on 4/16/2004 ; 感谢LeXRus提供 RSS 2.0 文档; 此文件可自由使用，但请保留此行信息 --> 
<!-- Source download URL: http://blogger.org.cn/blog/rss2.asp       -->
<rss version="2.0">

<channel>
<title>Areyan's Blog</title>
<link>http://blogger.org.cn/blog/blog.asp?name=areyan</link>
<description>阿严的博客</description>
<copyright>blogger.org.cn</copyright>
<generator>W3CHINA Blog</generator>
<webMaster>webmaster@blogger.org.cn</webMaster>
<item>
<title><![CDATA[搬了新家]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=48519</link>
<author>areyan</author>
<pubDate>2010/3/28 0:35:17</pubDate>
<description><![CDATA[本人已经搬了新家到百度，可以通过以下路径访问：<A href="http://hi.baidu.com/areyan">http://hi.baidu.com/areyan</A>]]></description>
</item><item>
<title><![CDATA[无用存储单元收集器工作小谈]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14774</link>
<author>areyan</author>
<pubDate>2006/5/27 11:43:30</pubDate>
<description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 23.15pt; mso-char-indent-count: 2.57; mso-char-indent-size: 9.0pt"><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">无用存储单元收集器是因为中间语言是为处理该过程而工作的。其规则要求，第一，不能引用已有的对象，除百复制已有的引用。第二，中间语言的类型安全的语言。在这里，其含义是如果存在对对象的任何引用，该引用中就有足够的信息来确定对象的类型。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 23.15pt; mso-char-indent-count: 2.57; mso-char-indent-size: 9.0pt"><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">无用存储单收集机制不能和诸如未受管制的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">C</FONT></SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">＋＋这样的语言一起使用，因为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">C</FONT></SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">＋＋允许在类型之间使用指针自由地转换数据类型。这样，搜索代码的程序就找不到指针的值，不能获得足够的信息来确定堆的什么区域正在使用。如前氘核，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">IL</FONT></SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">还允许在不安全的代码中使用指针，以及在指针之间转换数据类型。但使用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">IL</FONT></SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt">，会严格限制使用这些指针的方式，以确保在代码中使用的指针不与无用存储单元收集器的需求冲突。特别是指针不允许设置为指向引用对象。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt">无用存储单元收集器的一个重要方面是它是不确定的。换言这，不能保证什么时候会调用无用存储单元收集器；</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体; mso-bidi-font-size: 12.0pt">.NET</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt">运行时决定需要它时，就可以调用它。显然，代码对内存的需求越多，无用存储单元收集器的调用次数就越多。但其次数是可以预计的。在代码中，可以使用</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体; mso-bidi-font-size: 12.0pt">.NET</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt">基类</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体; mso-bidi-font-size: 12.0pt">System.GC</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt">显式地调用无用存储单收集器，例如，可以在代码使用完大量的变量后调用它。但在大多数情况下，只需委托</SPAN><SPAN lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体; mso-bidi-font-size: 12.0pt">.NET</SPAN><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt">运行时在合适的时候调用无用存储单元收集器即可。</SPAN>]]></description>
</item><item>
<title><![CDATA[COM中语言互操作的含义]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14770</link>
<author>areyan</author>
<pubDate>2006/5/27 1:19:14</pubDate>
<description><![CDATA[&nbsp;&nbsp;&nbsp; COM是一个二进制标准，允许组件实例其它组件，调用它们的方法或属性，而无需考虑编写相关组件的语言。但为了实现这个功能，每个对象都必须通过COM运行时来实例，通过接口来访问。不仅如此，根据关系组件的纯种模型，不同纯种上内存空间和运行组件之间要编组数据，这还可能赞成很大的性能损失。在极端情况下，组件驻留在可执行文件中，而不是DLL文件中，还必须创建单独的过程来运行它们。重要的是组件要能与其它组件通信，但仅通过COM运行时进行通信。无论COM是用于允许使用不同语言的组件直接彼此通信，或者创建彼此的实例，系统都把COM作为中间件来处理。不仅如此，COM结构还不允许利用继承实现，即它丧失了面向对象编程的优势。<A></A>]]></description>
</item><item>
<title><![CDATA[.NET中强类型化功能的重要性]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14769</link>
<author>areyan</author>
<pubDate>2006/5/27 1:17:35</pubDate>
<description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US>.NET Framework如果没有这个功能就不能工作：首先，Common Language Runtime可以在运行代码前检查代码，以确定代码需要执行什幺操作。第二，为了正确区分可以释放的内存，无用存储单元收集器必须能明确地知道每个内存位置都存储了什幺样的数据类型(如果做不到，就无法知道变量占用了多少内存)。数据类型上的任何含糊都会导致问题的出现，妨碍.NET运行的正确执行。第三，语言的互操作性是.NET Framework的一个主要卖点，它主要信赖于设计合理和具有一致性的数据类型信。</SPAN></SPAN></P>]]></description>
</item><item>
<title><![CDATA[中间语言中接口的概念]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14768</link>
<author>areyan</author>
<pubDate>2006/5/27 1:16:23</pubDate>
<description><![CDATA[<SPAN style="FONT-FAMILY: 宋体"><SPAN lang=EN-US>.NET接口与COM接口不同，它们不需要支持任何COM基类结束。但它们与COM共享了以下一个概念：提供一个契约，在执行指定接口的类时，必须提供接口指定的方法和属性的实现方式。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></SPAN></SPAN>]]></description>
</item><item>
<title><![CDATA[运行受管制代码的优点]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14767</link>
<author>areyan</author>
<pubDate>2006/5/27 1:12:01</pubDate>
<description><![CDATA[<P><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-size: 12.0pt"><SPAN lang=EN-US>1.在安全性方面有明显的优势,因为装配件是用中间语言编写的，所以.NET运行时可以检查代码要完成什幺样的工作，可以更安全地运行已经得到的代码。2.无用存储单元收集器将使用户不再需要编写明确的代码来释放已使用过的内存，这还意味着由无用存储单元收集器管理的所有变量都没有内存溃漏的问题。3.应用域的新概念意味着不同的应用程序需要在同一个过程中彼此独立，又能彼此通信，大大提高了性能。4.使用语言拥有语言的互操作性，可以更轻松地使用多种语言编写的代码。5.装配件的自我描述结构杜绝了因版本冲突问题或其它应用程序覆盖共享装配件而产生的错误。6..NET基类提供了一个非常直观、简单的对象模型，它可以比过去更方便地调用Windows的大多数功能，简化了源代码。</SPAN></SPAN></P>]]></description>
</item><item>
<title><![CDATA[DotNet 中CLR的运行和编译模式]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14766</link>
<author>areyan</author>
<pubDate>2006/5/27 0:42:29</pubDate>
<description><![CDATA[<P><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy">.NET程序运行前必须编译，被编译后的程序代码不包括汇编程序指使，而是包括MSIL(Microsoft Intermediate Language指命，它是一种非常低级的语言，可以快速地由(JIT编译)为内部机械代码!</SPAN></P>
<P><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy"><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><IMG style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" src="http://blogger.org.cn/blog/uploadfile/20065271116441.JPG" border=0></o:p></SPAN></P>
<P><SPAN style="FONT-SIZE: 10pt; COLOR: navy">携带编译好的程序的软件包由许多装配件组成。每个装配件都包含中间语言代码，也包含元数据，代描述装配件中的数据类型和方法。元数据还包括装配件内容的一个简单散列，用于验证该装配件没有被塞满，它还包含版本信息，该装配件调用其它装配件的信息，以及控制权限的信息，代码必须有这些权限才能运行。该程序包含许多装配件，其中一个装配件被指定为一个可执行程序，包含主程序的激活入口点，其它装配件则指定为库。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></P><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">当运行程序时，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">首先会加载第一个装配件</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">-</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">包括程序主入口的装配件。第二步就是验证代码的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">“</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">内存类型的安全性</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">”</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">。如果代码只以</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">可以控制的方式访问内存，它就是安全的内存类型。其重要性在于内存类型安全的代码可以保证不读写不属于它的任何内存。这是很重要的，因为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">.NET</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">有一种机制</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">(</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">应用域</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">)</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">，允许多个应用程序运行在同一个过程中，如果是这样，就需要保证任何应用程序都不会访问其它应用程序的内存。如果</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">不能验证代码是内存类型安全的，根据本地安全策略，它就会拒绝运行代码。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">最后就会运行代码。它为运行的代码创建一个过程，并标记应用域，在该域中放入程序的主纯种。在某些情况下，程序可以请求不放在与其它运行代码相同的过程中，此时</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">只会为该程序创建一个新的应用域。然后，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">提取代码中需要运行的第一部分，把它从中间语言编译为汇编语言，再在合适的程序纯种中执行它，每次执行流到达一个以前没有执行过的新方法时，该方法就会编译为可执行代码。但这个编译过程只进行一次。该方法编译的、完后，其入口的地址就被编译好的可执行代码地址所替换。这样，就维护了性能，因为代码中只有实际要使用的部分才会被编译。这个过程称为</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">just-in-time</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">编译。注意</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">JIT</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">编译器在编译时，会根据在装配件中指定的编译设置优化代码。运行代码时，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">CLR</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">会监视其内存的使用。根据监视结果，它在某些情况下会临时中断执行一小段时间</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">(</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">一般是几毫秒</SPAN><SPAN lang=EN-US style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体">)</SPAN><SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">，调用无用存储单元收集器，检查程序中的变量，以确定哪些内存区域仍处于满打满算状态，即代码仍在使用它们，而释放不再使用的区域。</SPAN>]]></description>
</item><item>
<title><![CDATA[[轉]避免LEFT JOIN 和 NULL]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14413</link>
<author>areyan</author>
<pubDate>2006/5/15 11:59:40</pubDate>
<description><![CDATA[<SPAN class=spnMessageText id=msg><FONT color=#191970 size=2>避免LEFT JOIN 和 NULL <BR><BR><BR>當然，有很多時候您需要執行LEFT JOIN 和使用 NULL 值。但是，它們並不適用於所有情況。改變 SQL 查詢的構建方式可能會#29987;生將一個花幾分鐘運行的報告縮短到只花幾秒鐘這樣的天壤之別的效果。有時，必須在查詢中調整資料的形態，使之適應應用程式所要求的顯示方式。雖然 TABLE 資料類型會減少大量佔用資源的情況，但在查詢中還有許多區域可以進行優化。SQL 的一個有價值的常用功能是 LEFT JOIN。它可以用於檢索第一個表中的所有行、第二個表中所有匹配的行、以及第二個表中與第一個表不匹配的所有行。例如，如果希望返回每個客戶及其定單，使用 LEFT JOIN 則可以顯示有定單和沒有定單的客戶。<BR><BR>此工具可能會被過度使用。LEFT JOIN 消耗的資源非常之多，因為它們包含與 NULL（不存在）資料匹配的資料。在某些情況下，這是不可避免的，但是代價可能非常高。LEFT JOIN 比 INNER JOIN 消耗資源更多，所以如果您可以重新編寫查詢以使得該查詢不使用任何 LEFT JOIN，則會得到非常可觀的回報。 <BR><BR>加快使用LEFT JOIN 的查詢速度的一項技術涉及創建一個 TABLE 資料類型，插入第一個表（LEFT JOIN 左側的表）中的所有行，然後使用第二個表中的值更新 TABLE 資料類型。此技術是一個兩步的過程，但與標準的 LEFT JOIN 相比，可以節省大量時間。一個很好的規則是嘗試各種不同的技術並記錄每種技術所需的時間，直到獲得用於您的應用程式的執行性能最佳的查詢。 <BR><BR>測試查詢的速度時，有必要多次運行此查詢，然後取一個平均值。因#29234;查詢（或存儲過程）可能會存儲在SQL Server 記憶體中的過程緩存中，因此第一次嘗試耗費的時間好像稍長一些，而所有後續嘗試耗費的時間都較短。另外，運行您的查詢時，可能正在針對相同的表運行其他查詢。當其他查詢鎖定和解鎖這些表時，可能會導致您的查詢要排隊等待。例如，如果您進行查詢時某人正在更新此表中的資料，則在更新提交時您的查詢可能需要耗費更長時間來執行。 <BR><BR>避免使用LEFT JOIN 時速度降低的最簡單方法是盡可能多地圍繞它們設計資料庫。例如，假設某一#29987;品可能具有類別也可能沒有類別。如果 Products 表存儲了其類別的 ID，而沒有用於某個特定產品的類別，則您可以在欄位中存儲 NULL 值。然後您必須執行 LEFT JOIN 來獲取所有#29987;品及其類別。您可以創建一個值為“No Category”的類別，從而指定外鍵關係不允許 NULL 值。通過執行上述操作，現在您就可以使用 INNER JOIN 檢索所有產品及其類別了。雖然這看起來好像是一個帶有多餘資料的變通方法，但可能是一個很有價值的技術，因為它可以消除 SQL 批次處理語句中消耗資源較多的 LEFT JOIN。在資料庫中全部使用此概念可以為您節省大量的處理時間。請記住，對於您的用戶而言，即使幾秒鐘的時間也非常重要，因為當您有許多用戶正在訪問同一個聯機資料庫應用程式時，這幾秒鐘實際上的意義會非常重大。</FONT><BR></SPAN>]]></description>
</item><item>
<title><![CDATA[[转]数据库索引应用]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14382</link>
<author>areyan</author>
<pubDate>2006/5/13 22:58:43</pubDate>
<description><![CDATA[<DIV class=postTitle>数据库索引应用</DIV>
<P><BR><SPAN style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">一、索引的概念<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中，索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中，索引也允许数据库程序迅速地找到表中的数据，而不必扫描整个数据库。<SPAN lang=EN-US><BR><BR></SPAN>二、索引的特点<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 1.</SPAN>索引可以加快数据库的检索速度<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 2.</SPAN>索引降低了数据库插入、修改、删除等维护任务的速度<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 3.</SPAN>索引创建在表上，不能创建在视图上<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 4.</SPAN>索引既可以直接创建，也可以间接创建<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 5.</SPAN>可以在优化隐藏中，使用索引<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 6.</SPAN>使用查询处理器执行<SPAN lang=EN-US>SQL</SPAN>语句，在一个表上，一次只能使用一个索引<SPAN lang=EN-US>&nbsp;<BR>&nbsp;&nbsp;&nbsp; 7.</SPAN>其他<SPAN lang=EN-US><BR><BR></SPAN>三、索引的优点<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 1.</SPAN>创建唯一性索引，保证数据库表中每一行数据的唯一性<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 2.</SPAN>大大加快数据的检索速度，这也是创建索引的最主要的原因<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 3.</SPAN>加速表和表之间的连接，特别是在实现数据的参考完整性方面特别有意义。<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 4.</SPAN>在使用分组和排序子句进行数据检索时，同样可以显著减少查询中分组和排序的时间。<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 5.</SPAN>通过使用索引，可以在查询的过程中使用优化隐藏器，提高系统的性能。<SPAN lang=EN-US><BR><BR></SPAN>四、索引的缺点<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 1.</SPAN>创建索引和维护索引要耗费时间，这种时间随着数据量的增加而增加<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 2.</SPAN>索引需要占物理空间，除了数据表占数据空间之外，每一个索引还要占一定的物理空间，如果要建立聚簇索引，那么需要的空间就会更大<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 3.</SPAN>当对表中的数据进行增加、删除和修改的时候，索引也要动态的维护，降低了数据的维护速度<SPAN lang=EN-US><BR><BR></SPAN>五、索引分类<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 1.</SPAN>直接创建索引和间接创建索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; </SPAN>直接创建索引：<SPAN lang=EN-US> CREATE INDEX mycolumn_index ON mytable (myclumn)<BR>&nbsp;&nbsp;&nbsp; </SPAN>间接创建索引：定义主键约束或者唯一性键约束，可以间接创建索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 2.</SPAN>普通索引和唯一性索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; </SPAN>普通索引：<SPAN lang=EN-US>CREATE INDEX mycolumn_index ON mytable (myclumn)<BR>&nbsp;&nbsp;&nbsp; </SPAN>唯一性索引：保证在索引列中的全部数据是唯一的，对聚簇索引和非聚簇索引都可以使用<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)<BR>&nbsp;&nbsp;&nbsp; 3.</SPAN>单个索引和复合索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; </SPAN>单个索引：即非复合索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; </SPAN>复合索引：又叫组合索引，在索引建立语句中同时包含多个字段名，最多<SPAN lang=EN-US>16</SPAN>个字段<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; CREATE INDEX name_index ON username(firstname,lastname)<BR>&nbsp;&nbsp;&nbsp; 4.</SPAN>聚簇索引和非聚簇索引<SPAN lang=EN-US>(</SPAN>聚集索引，群集索引<SPAN lang=EN-US>)<BR>&nbsp;&nbsp;&nbsp;</SPAN>聚簇索引：物理索引，与基表的物理顺序相同，数据值的顺序总是按照顺序排列<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH<BR>&nbsp;&nbsp;&nbsp; ALLOW_DUP_ROW(</SPAN>允许有重复记录的聚簇索引<SPAN lang=EN-US>)<BR>&nbsp;&nbsp;&nbsp;</SPAN>非聚簇索引：<SPAN lang=EN-US>CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)<BR><BR></SPAN>六、索引的使用<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp;1.</SPAN>当字段数据更新频率较低，查询使用频率较高并且存在大量重复值是建议使用聚簇索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp;&nbsp;2.</SPAN>经常同时存取多列，且每列都含有重复值可考虑建立组合索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 3.</SPAN>复合索引的前导列一定好控制好，否则无法起到索引的效果。如果查询时前导列不在查询条件中则该复合索引不会被使用。前导列一定是使用最频繁的列<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 4.</SPAN>多表操作在被实际执行前，查询优化器会根据连接条件，列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表；内外表的选择可由公式：外层表中的匹配行数<SPAN lang=EN-US>*</SPAN>内层表中每一次查找的次数确定，乘积最小为最佳方案<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 5.where</SPAN>子句中对列的任何操作结果都是在<SPAN lang=EN-US>sql</SPAN>运行时逐列计算得到的，因此它不得不进行表搜索，而没有使用该列上面的索引；如果这些结果在查询编译时就能得到，那么就可以被<SPAN lang=EN-US>sql</SPAN>优化器优化，使用索引，避免表搜索<SPAN lang=EN-US>(</SPAN>例：<SPAN lang=EN-US>select * from record where substring(card_no,1,4)=</SPAN>’<?XML:NAMESPACE PREFIX = U1 /><U1:CHMETCNV TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="5378" UnitName="’" u2:st="on"><?XML:NAMESPACE PREFIX = ST1 /><ST1:CHMETCNV TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="5378" UnitName="’" w:st="on"><SPAN lang=EN-US>5378</SPAN>’</U1:CHMETCNV></ST1:CHMETCNV><SPAN lang=EN-US> <BR>&amp;&amp; select * from record where card_no like </SPAN>’<SPAN lang=EN-US>5378%</SPAN>’<SPAN lang=EN-US>)</SPAN>任何对列的操作都将导致表扫描，它包括数据库函数、计算表达式等等，查询时要尽可能将操作移至等号右边<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 6.where</SPAN>条件中的’<SPAN lang=EN-US>in</SPAN>’在逻辑上相当于’<SPAN lang=EN-US>or</SPAN>’，所以语法分析器会将<SPAN lang=EN-US>in ('0','1')</SPAN>转化为<SPAN lang=EN-US>column='0' or column='1'</SPAN>来执行。我们期望它会根据每个<SPAN lang=EN-US>or</SPAN>子句分别查找，再将结果相加，这样可以利用<SPAN lang=EN-US>column</SPAN>上的索引；但实际上它却采用了<SPAN lang=EN-US>"or</SPAN>策略<SPAN lang=EN-US>"</SPAN>，即先取出满足每个<SPAN lang=EN-US>or</SPAN>子句的行，存入临时数据库的工作表中，再建立唯一索引以去掉重复行，最后从这个临时表中计算结果。因此，实际过程没有利用<SPAN lang=EN-US>column</SPAN>上索引，并且完成时间还要受<SPAN lang=EN-US>tempdb</SPAN>数据库性能的影响。<SPAN lang=EN-US>in</SPAN>、<SPAN lang=EN-US>or</SPAN>子句常会使用工作表，使索引失效；如果不产生大量重复值，可以考虑把子句拆开；拆开的子句中应该包含索引<SPAN lang=EN-US><BR>&nbsp;&nbsp;&nbsp; 7.</SPAN>要善于使用存储过程，它使<SPAN lang=EN-US>sql</SPAN>变得更加灵活和高效</SPAN></P>]]></description>
</item><item>
<title><![CDATA[[转]ASP.NET基于角色的窗体安全认证机制]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14381</link>
<author>areyan</author>
<pubDate>2006/5/13 22:54:49</pubDate>
<description><![CDATA[ASP.NET基于角色的窗体安全认证机制<BR><BR>说明：两个月前我刚学 ASP.NET， 在 codeproject.com 看到题目叫 Role-based Security with Forms Authentication 的文章，觉得很有帮助。当时就想翻译成中文。不过直接翻译实在没意思，这两天我参照 Heath Stewart的这篇文章，并且根据自己的理解，把它按照自己的想法和表达方式写成中文。附带上自己为这篇文章做的一个演示的web应用程序。<BR>如果有理解错误的地方，欢迎来信指出或发表评论。<BR><BR>附：垃圾邮件实在讨厌，请高抬贵手。 <BR><BR>原文章在 <A href="http://www.codeproject.com/aspnet/formsroleauth.asp" target=_blank>http://www.codeproject.com/aspnet/formsroleauth.asp</A><BR>原作者 Heath Stewart<BR><BR><BR>概要：<BR>ASP.NET 提供了基于角色（即 Roles）的认证机制，然而它对角色的支持是不完全的。本文试图通过一些例子来说明如何实现和使用这种基于角色的认证机制。 <BR><BR>简介：<BR><BR>ASP.NET 中窗体认证是一个功能非常强大的特性，只需要很少的代码就可以实现一个简单的平台无关的安全认证系统。<BR>但是，如果你需要一个更复杂更有效的认证机制，那么你就要把众多用户分成用户群组，以利用它的灵活性。Windows 集成认证提供了这种认证机制，但它使用的是 NTLM，即Windows NT LAN Manager，因而它不是跨平台的。现在越来越多的人使用 Linux 系统，而 Mozilla Forefox 浏览器用户也越来越多，我们肯定不能把这些人拒之门外，因此我们寻求另外的认证机制。有两个选择：一是为网站划分多个区域，提供多个登录页面，强迫用户一个一个的去注册和登录；二是把用户分组，并且限制特定用户组对某页面或者某区域访问的权限。后者当然是更好的选择。通过分配角色给各个用户，我们能够实现这种功能。 <BR><BR>微软为.NET平台留下了窗体认证中基于角色的认证机制，但是我们必须自己去实现它。本文力求覆盖窗体认证中基于角色的认证机制的一些基本的东西，比如它的概念，它的实现，如何在Web应用程序中应用等。<BR><BR><BR>必要准备：<BR>我们首先要建立一个数据库，一个Web应用项目，几个不同安全级别的机密目录，以及几个ASP.NET页面。当然你也可以在你现有的Web应用项目中添加这些。<BR><BR>1、创建数据库<BR><BR>首先要选择你需要使用的数据库管理系统 DBMS。本文使用 SQL Server 2000。<BR><BR>在实际应用项目的数据库中，一般都会有用户数据表 Users，它可能包括用户唯一标记：UserID，用户名：UserName，密码：Password，用户的邮件地址：Email，用户所在城市：City，用户登录次数 LoginCount 等。可以通过创建一个 UserInRoles 数据表（一般可以包括两个字段，用户名：UserName，用户角色：UserRoles）来实现为用户分配角色。 <BR><BR><BR>为了简单，我只创建一个 Users 数据表，它有3个字段，用户名 UserName，密码 Password，用户角色 UserRoles。创建表之前，你要选择数据库，或者创建一个新的数据库。要创建一个新的命名为WebSolution的数据库 ，只需要简单的SQL语句：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>Create DATABASE WebSolution<BR>GO</DIV></DIV><BR>要选择一个叫msdb的数据库，可以使用SQL语句：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>USE msdb<BR>GO</DIV></DIV><BR><BR>接下来，我们创建刚才提到的 Users 数据表，SQL 脚本如下：<BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent><BR>Create TABLE Users<BR>(<BR>UserName nvarchar(100) CONSTRAINT PK_UserName PRIMARY KEY,<BR>Password nvarchar(150),<BR>UserRoles nvarchar(100)<BR>)</DIV></DIV><BR>可以为这个表创建索引 Credentials，SQL语句如下：<BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent><BR>Create INDEX Credentials ON Users<BR>(<BR>UserName,<BR>Password<BR>)</DIV></DIV>是否创建索引是可选的，由你自己决定。索引的好处和坏处请参考相关资料。<BR><BR>然后我们为这个Users数据库添加数据。角色名称由你自己自由选择，但是最好用有意义的名称，比如<BR>"Administrator"（顶级管理员），"Manager"（管理员），"Member"（加盟成员），"User"（普通用户）等。例如：<BR><STRONG><BR>UserName|Password|Roles<BR>"willmove"|"pwd123"|"Administrator,User"<BR>"amuhouse"|"pwd123"|"User" </STRONG><BR><BR>其SQL语句是：<BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent><BR>--注意 '45CB41B32DCFB917CCD8614F1536D6DA' 是 'pwd123' 使用 md5 加密后的字符串<BR>Insert INTO Users(UserName,Password,UserRoles) VALUES ('willmove','45CB41B32DCFB917CCD8614F1536D6DA','Administrator,User')<BR>GO<BR>Insert INTO Users(UserName,Password,UserRoles) VALUES ('amuhouse','45CB41B32DCFB917CCD8614F1536D6DA','User')<BR>GO</DIV></DIV><BR><BR>要注意的是角色 Roles 是大小写敏感的，这是因为在 Web.config 文件中是大小写敏感的。现在我们为实现这个安全认证机制创建几个必要的页面。<BR>首先是用户登录页面 Login.aspx <BR>如果还没有创建Web应用程序，那就现在创建一个。当然你也可以在一个已有的Web应用程序中创建这个页面。这里我假设已经创建了一个名称为 RolebasedAuth的Web应用程序（即 Visual Studio .Net 中的Project）。我把这个Login.aspx放在它的根目录下，也就是通过 <A href="http://localhost/RolebasedAuth/Login.aspx" target=_blank>http://localhost/RolebasedAuth/Login.aspx</A> 可以访问。<BR>这个Login.aspx放在哪里是无所谓的，但是它必须是公众有权限访问的。<BR><BR>在应用程序根路径下，我们创建两个机密的子目录，分别是 Admin 和 User。<BR><BR><BR>接下来，我们创建一个支持角色认证的窗体认证登录系统。因为微软没有提供简单的实现机制，我们要自己花些时间去创建认证票据。它需要存贮少量信息，当然，有些名称必须和 Web.config 中配置的一样，要不ASP.NET 就会认为你的认证票据是无效的，从而强制转向到登录页面。我们在 VS.NET 中为 Login.aspx 添加两个TextBox控件，取名 UserNameTextBox, PasswordTextBox，再添加一个Button，取名 LoginButton，点击它进入后台代码。在 LoginButton_Click 方法中添加需要的代码。如下：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>private void LoginButton_Click(object sender, System.EventArgs e)<BR>{<BR>// 初始化 FormsAuthentication<BR>// 注意它是在 System.Web.Security 命名空间<BR>// 因此要在代码开始添加 using System.Web.Security;<BR>FormsAuthentication.Initialize ();<BR><BR>// 创建数据库连接和数据库操作命令对象<BR>// 注意它是在 System.Data.SqlClient 命名空间<BR>// 因此要在代码开始处添加 using System.Data.SqlClient;<BR>SqlConnection conn =<BR>new SqlConnection("Data Source=sun-willmove;integrated security=SSPI;Initial Catalog=WebSolution;"); <BR>SqlCommand cmd = conn.CreateCommand();<BR>cmd.CommandText = "Select UserRoles FROM Users Where UserName=@username " +<BR>"AND Password=@password";<BR>// 填充各个参数 <BR>cmd.Parameters.Add("@username", SqlDbType.NVarChar, 100).Value =<BR>UserNameTextBox.Text;<BR>cmd.Parameters.Add("@password", SqlDbType.NVarChar, 150).Value = <BR>FormsAuthentication.HashPasswordForStoringInConfigFile(<BR>PasswordTextBox.Text, "md5"); // 或者 "sha1"<BR><BR>// 执行数据库操作命令<BR>conn.Open();<BR>SqlDataReader reader = cmd.ExecuteReader();<BR>if (reader.Read())<BR>{<BR>// 为了实现认证，创建一个新的票据<BR>FormsAuthenticationTicket ticket = new FormsAuthenticationTicket( <BR>1, // 票据版本号<BR>UserNameTextBox.Text, // 票据持有者<BR>DateTime.Now, //分配票据的时间<BR>DateTime.Now.AddMinutes(30), // 失效时间<BR>true, // 需要用户的 cookie <BR>reader.GetString(0), // 用户数据，这里其实就是用户的角色<BR>FormsAuthentication.FormsCookiePath);//cookie有效路径<BR><BR>//使用机器码machine key加密cookie，为了安全传送<BR>string hash = FormsAuthentication.Encrypt(ticket);<BR>HttpCookie cookie = new HttpCookie(<BR>FormsAuthentication.FormsCookieName, // 认证cookie的名称<BR>hash); //加密之后的cookie<BR><BR>//将cookie的失效时间设置为和票据tikets的失效时间一致 <BR>if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;<BR><BR>//添加cookie到页面请求响应中<BR>Response.Cookies.Add(cookie);<BR><BR>// 将用户转向到之前请求的页面，<BR>// 如果之前没有请求任何页面，就转向到首页 <BR>string returnUrl = Request.QueryString["ReturnUrl"];<BR>if (returnUrl == null) returnUrl = "./";<BR><BR>// 不要调用 FormsAuthentication.RedirectFromLoginPage 方法，<BR>// 因为它会把刚才添加的票据（cookie）替换掉<BR>Response.Redirect(returnUrl);<BR>}<BR>else<BR>{<BR>// 不要告诉用户"密码错误"，这样等于给了入侵者一个机会，<BR>// 因为他们知道了他们输入的用户名是存在的 <BR>// <BR>ErrorLabel.Text = "用户名或者密码错误，请重试！";<BR>ErrorLabel.Visible = true;<BR>}<BR><BR>reader.Close();<BR>conn.Close();<BR>} </DIV></DIV><BR>前台 aspx 页面代码如下：<BR><BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>&lt;%@ Page language="c#" Codebehind="Login.aspx.cs" AutoEventWireup="false" Inherits="RolebasedAuth.Login" %&gt;<BR>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" &gt;<BR>&lt;HTML&gt;<BR>&lt;HEAD&gt;<BR>&lt;title&gt;Login&lt;/title&gt;<BR>&lt;meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1"&gt;<BR>&lt;meta name="CODE_LANGUAGE" Content="C#"&gt; <BR>&lt;meta name="vs_defaultClientScript" content="JavaScript"&gt;<BR>&lt;meta name="vs_targetSchema" content="<A href="http://schemas.microsoft.com/intellisense/ie5" target=_blank>http://schemas.microsoft.com/intellisense/ie5</A> "&gt;<BR>&lt;/HEAD&gt;<BR>&lt;body&gt;<BR>&lt;form id="Form1" method="post" runat="server"&gt;<BR>&lt;P&gt;<BR>&lt;asp:Label id="Label1" runat="server"&gt;用户名:&lt;/asp:Label&gt; <BR>&lt;asp:TextBox id="UserNameTextBox" runat="server"&gt;&lt;/asp:TextBox&gt;&lt;/P&gt;<BR>&lt;P&gt;&lt;FONT face="宋体"&gt;&nbsp; &lt;/FONT&gt;<BR>&lt;asp:Label id="Label2" runat="server"&gt;密码:&lt;/asp:Label&gt; <BR>&lt;asp:TextBox id="PasswordTextBox" runat="server" TextMode="Password"&gt;&lt;/asp:TextBox&gt;&lt;/P&gt;<BR>&lt;P&gt;<BR>&lt;asp:Label id="ErrorLabel" runat="server" Visible="False"&gt;&lt;/asp:Label&gt;&lt;/P&gt; <BR>&lt;P&gt;<BR>&lt;asp:Button id="LoginButton" runat="server" Text="登录"&gt;&lt;/asp:Button&gt;&lt;/P&gt;<BR>&lt;/form&gt;<BR>&lt;/body&gt;<BR>&lt;/HTML&gt; </DIV></DIV><BR><BR>你会注意到上面我们对密码的处理：将它哈希加密。哈希加密是一种单向算法（不可逆算法），生成唯一的字符数组。因此即使是改变密码中一个字母的大小写，都会生成完全不同的哈希列。我们把这些加密的密码存储在数据库中，这样更安全。在实际应用中，你可能想为用户找回忘记的密码。但是哈希散列是不可逆的，所以你就不可能恢复原来的密码。但是你可以更改用户的密码，并且把这个更改后的密码告诉他。如果一个网站能够给你旧密码，那么你要考虑清楚了，你的用户数据是不安全的！事实上，国内大部分网站都是没有经过加密直接把用户的密码存储到数据库中的。如何一个黑客入侵成功，那么这些用户帐户就很危险了！ <BR><BR>如果没有使用SSL，你的密码在网络中也是以明文传输的。传输过程中可能会被窃取。在服务器端加密密码只能保证密码存储的安全。SSL相关的资料可以在 <A href="http://www.versign.com/" target=_blank>http://www.versign.com</A> 或 <A href="http://www.thewte.com/" target=_blank>http://www.thewte.com</A> 中找到。<BR><BR>如果你不想以加密方式在数据库中存储密码，你可以更改上面的代码，把 <BR>FormsAuthentication.HashPasswordForStoringInConfigFile(PasswordTextBox.Text, "md5") 改成 PasswordTextBox.Text 即可。<BR><BR>下一步，我们需要修改 Global.asax 文件。如果你的Web应用程序没有这个文件，请右键单击Web应用项目，选择 "添加-&gt;添加新项...-&gt;Global Application Class"。在 Global.asax 或者 Global.asax.cs 中，找到叫做 Application_AuthenticationRequest 的方法（函数）。先要确认已经包含或者使用了 System.Security.Principal 以及 System.Web.Security 命名空间，然后修改它，修改后的代码：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>protected void Application_AuthenticateRequest(Object sender, EventArgs e) <BR>{<BR>if (HttpContext.Current.User != null)<BR>{<BR>if (HttpContext.Current.User.Identity.IsAuthenticated)<BR>{<BR>if (HttpContext.Current.User.Identity is FormsIdentity)<BR>{<BR>FormsIdentity id =<BR>(FormsIdentity)HttpContext.Current.User.Identity;<BR>FormsAuthenticationTicket ticket = id.Ticket;<BR><BR>// 取存储在票据中的用户数据，在这里其实就是用户的角色<BR>string userData = ticket.UserData;<BR>string[] roles = userData.Split(',');<BR>HttpContext.Current.User = new GenericPrincipal(id, roles);<BR>}<BR>}<BR>}<BR><BR>}</DIV></DIV><BR><BR>认证票据（用户名和密码）是没有作为cookie的一部分来存储的，而且也不可以，因为用户可以修改他们的cookie。<BR>事实上，FormsAuthentication是用你的机器码 （machine key，通常在 machine.config 中）来加密票据（FormsAuthenticationTicket）的。我们使用 UserData 存储用户角色，并且生成一个新的凭证。一旦凭证已经创建，它会被添加到当前上下文中（即 HttpContext），这样就可以用它来取回用户角色了。<BR><BR>接下来，我们设置机密目录（也就是"安全目录"，特定的使用者如管理员才有权限访问的目录）。首先看看你的Web应用程序根目录下是否有 Web.config 这个文件，如果没有就创建一个。你也可以在你的子目录中创建 Web.config 文件，当然，这个 Web.config 文件是有限制的（一些参数它不可以设置）。要实现安全认证，在 Web应用程序根目录下的 Web.config 文件中找到 &lt;system.web&gt; 节点下的 <BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>&lt;authentication mode="Windows" /&gt;，把它修改为<BR><BR>&lt;authentication mode="Forms"&gt; <BR>&lt;forms name="AMUHOUSE.ASPXAUTH"<BR>loginUrl="Login.aspx"<BR>protection="All"<BR>path="./" /&gt;<BR>&lt;/authentication&gt; <BR>&lt;authorization&gt;<BR>&lt;allow users="*"/&gt;<BR>&lt;/authorization&gt;</DIV></DIV><BR>上面的 name="AMUHOUSE.ASPXAUTH" 中，AMUHOUSE.ASPXAUTH 这个名称是任意的。要控制用户或者用户组的权限，我们可以有两种方法，一是配置在应用程序根目录下的 Web.config 文件，二是在机密目录下创建一个独立的 Web.config 文件。（后者也许会比较好。）如果是前者，这个Web.config 就应该包含有下面的内容（或者类似的内容）：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>&lt;configuration&gt;<BR>&lt;system.web&gt;<BR>&lt;authentication mode="Forms"&gt;<BR>&lt;forms name=" AMUHOUSE.ASPXAUTH"<BR>loginUrl="login.aspx"<BR>protection="All"<BR>path="/"/&gt;<BR>&lt;/authentication&gt;<BR>&lt;authorization&gt; <BR>&lt;allow users="*"/&gt;<BR>&lt;/authorization&gt;<BR>&lt;/system.web&gt;<BR>&lt;location path="./Admin"&gt;<BR>&lt;system.web&gt;<BR>&lt;authorization&gt; <BR>&lt;!-- 注意！下面几行的顺序和大小写是非常重要的！ --&gt;<BR>&lt;allow roles="Administrator"/&gt;<BR>&lt;deny users="*"/&gt;<BR>&lt;/authorization&gt;<BR>&lt;/system.web&gt; <BR>&lt;/location&gt;<BR>&lt;location path="./User"&gt;<BR>&lt;system.web&gt;<BR>&lt;authorization&gt;<BR>&lt;!-- 注意！下面几行的顺序和大小写是非常重要的！ --&gt;<BR>&lt;allow roles="User"/&gt; <BR>&lt;deny users="*"/&gt;<BR>&lt;/authorization&gt;<BR>&lt;/system.web&gt;<BR>&lt;/location&gt;<BR>&lt;/configuration&gt;</DIV></DIV><BR><BR>为了使Web应用程序的目录之前不互相依赖，可以比较方便的改名或者移动，可以选择在每一个安全子目录下配置单独的 Web.config 文件。它只需要配置 &lt;authorization/&gt;节点，如下：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>&lt;configuration&gt;<BR>&lt;system.web&gt;<BR>&lt;authorization&gt;<BR>&lt;!-- 注意！下面几行的顺序和大小写是非常重要的！ --&gt;<BR>&lt;allow roles="Administrator"/&gt; <BR>&lt;deny users="*"/&gt;<BR>&lt;/authorization&gt;<BR>&lt;/system.web&gt;<BR>&lt;/configuration&gt;</DIV></DIV><BR><BR>需要再次提醒的是，上面的角色 roles 是大小写敏感的，为了方便，你也可以把上面修改为：<BR>&lt;allow roles="Administrator,administrator" /&gt; <BR>如果你想允许或者禁止多个角色对这个目录的访问，可以用逗号隔开，如：<BR>&lt;allow roles="Administrator,Member,User" /&gt;<BR>&lt;deny users="*" /&gt;<BR><BR>至此，我们已经为网站配置了基于角色的安全认证机制了。你可以先编译你的程序，然后尝试访问一个机密目录，例如 <A href="http://localhost/RolebasedAuth/Admin" target=_blank>http://localhost/RolebasedAuth/Admin</A> ，这时候你就会被转向到用户登录页面。如果你登录成功，并且你的角色对这个目录有访问权限，你就重新回到这个目录下。可能会有用户（或入侵者）企图进入机密目录，我们可以使用一个 Session 来存储用户登录的次数，超过一定次数就不让用户登录，并且显示"系统拒绝了你的登录请求！"。<BR><BR>下面，我们讨论如何根据用户角色让Web控件显示不同内容。<BR><BR>有时候根据用户的角色来显示内容比较好，因为你可能不想为那么多不同的角色（用户群组）制作一大堆有许多重复内容的页面。这样的网站，各种用户帐户可以并存，付费的用户帐户能够访问附加的付费内容。另一个例子是一个页面将显示一个 "进入后台管理" 按钮链接到后台管理页面如果当前用户是 "Administrator"（高级管理员）角色。我们现在就实现这个页面。<BR>我们上面用到的 GenericPrincipal 类实现了 IPincipal 接口，这个接口有一个方法名叫做 IsInRole()，它的参数是一个字符串，这个字符串就是要验证的用户角色。如果我们要显示内容给角色是 "Administrator"的已登录用户，我们可以在 Page_Load 中添加下面代码： <BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>if (User.IsInRole("Administrator"))<BR>AdminLink.Visible = true;</DIV></DIV><BR>整个的页面代码如下（为了简便，把后台代码也写在aspx页面）：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>&lt;html&gt;<BR>&lt;head&gt;<BR>&lt;title&gt;欢迎您！&lt;/title&gt;<BR>&lt;script runat="server"&gt; <BR>protected void Page_Load(Object sender, EventArgs e)<BR>{<BR>if (User.IsInRole("Administrator"))<BR>AdminLink.Visible = true;<BR>else<BR>AdminLink.Visible = false;<BR>}<BR>&lt;/script&gt; <BR>&lt;/head&gt;<BR>&lt;body&gt;<BR>&lt;h2&gt;欢迎！&lt;/h2&gt;<BR>&lt;p&gt;欢迎来到阿木小屋 <A href="http://amuhouse.com/" target=_blank>http://amuhouse.com/</A> ^_^&lt;/p&gt;<BR>&lt;asp:HyperLink id="AdminLink" runat="server" <BR>Text="管理首页" NavigateUrl="./Admin"/&gt;<BR>&lt;/body&gt;<BR>&lt;/html&gt;</DIV></DIV><BR>这样，链接到 Admin 目录的HyperLink 控件只会显示给角色是 Administrator 的用户。你也可以根据为未登录用户提供一个链接到登录页面，如：<BR><BR>
<DIV class=UBBPanel>
<DIV class=UBBTitle><IMG style="MARGIN: 0px 2px -3px 0px" alt=程序代码 src="http://www.amuhouse.com/blog/images/code.gif"> 程序代码</DIV>
<DIV class=UBBContent>protected void Page_Load(object sender, System.EventArgs e)<BR>{<BR><BR>if (User.IsInRole("Administrator"))<BR>{<BR>AdminLink.Text = "管理员请进";<BR>AdminLink.NavigateUrl="./Admin"; <BR>}<BR>else if(User.IsInRole("User"))<BR>{<BR>AdminLink.Text = "注册用户请进";<BR>AdminLink.NavigateUrl="./User";<BR><BR>} <BR>else <BR>{<BR>AdminLink.Text = "请登录";<BR>AdminLink.NavigateUrl="Login.aspx?ReturnUrl=" + Request.Path;<BR>}<BR><BR>}</DIV></DIV><BR><BR>这里，我们通过设置叫做ReturnUrl的 QueryString 变量，可以使用户登录成功后返回到当前的这个页面. <BR><BR><BR>小结：<BR>本文用于帮助你理解基于角色安全机制的重要性、实用性，并且也用 ASP.NET 实现了基于角色的安全机制。它并不是一个很难实现的机制，不过它可能需要一些相关知识如 什么是用户凭证，如何认证用户身份，以及如何审定授权用户。如果你觉得它很有帮助，我会非常高兴。我希望它可以引导你在你的网站中去实现基于角色的窗体安全认证机制。]]></description>
</item><item>
<title><![CDATA[C#中构造函数和析构函数的用法]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14348</link>
<author>areyan</author>
<pubDate>2006/5/13 0:49:31</pubDate>
<description><![CDATA[C#中构造函数和析构函数的用法<BR>摘 要：构造函数与析构函数是一个类中看似较为简单的两类函数，但在实际运用过程中总会出现一些意想不到的运行错误。本文将较系统的介绍构造函数与析构函数的原理及在C#中的运用，以及在使用过程中需要注意的若干事项。 <BR>　　关键字：构造函数；析构函数；垃圾回收器；非托管资源；托管资源<BR>　　一．构造函数与析构函数的原理<BR>　　作为比C更先进的语言，C#提供了更好的机制来增强程序的安全性。C#编译器具有严格的类型安全检查功能，它几乎能找出程序中所有的语法问题，这的确帮了程序员的大忙。但是程序通过了编译检查并不表示错误已经不存在了，在“错误”的大家庭里，“语法错误”的地位只能算是冰山一角。级别高的错误通常隐藏得很深，不容易发现。<BR>　　根据经验，不少难以察觉的程序错误是由于变量没有被正确初始化或清除造成的，而初始化和清除工作很容易被人遗忘。微软利用面向对象的概念在设计C#语言时充分考虑了这个问题并很好地予以解决：把对象的初始化工作放在构造函数中，把清除工作放在析构函数中。当对象被创建时，构造函数被自动执行。当对象消亡时，析构函数被自动执行。这样就不用担心忘记对象的初始化和清除工作。<BR>　　二．构造函数在C#中的运用<BR>　　构造函数的名字不能随便起，必须让编译器认得出才可以被自动执行。它的命名方法既简单又合理：让构造函数与类同名。除了名字外，构造函数的另一个特别之处是没有返回值类型，这与返回值类型为void的函数不同。如果它有返回值类型，那么编译器将不知所措。在你可以访问一个类的方法、属性或任何其它东西之前， 第一条执行的语句是包含有相应类的构造函数。甚至你自己不写一个构造函数，也会有一个缺省构造函数提供给你。<BR>class TestClass<BR>{<BR>　public TestClass(): base() {} // 由CLR提供<BR>}&nbsp; <BR>　　下面列举了几种类型的构造函数<BR>　　1）缺省构造函数<BR>class TestClass<BR>{<BR>　public TestClass(): base() {} <BR>} <BR>　　上面已介绍，它由系统（CLR）提供。<BR>　　2）实例构造函数<BR>　　实例构造函数是实现对类中实例进行初始化的方法成员。如：<BR>using System;<BR>class Point<BR>{<BR>　public double x, y;<BR>　public Point() <BR>　{<BR>　　this.x = 0;<BR>　　this.y = 0;<BR>　}<BR>　public Point(double x, double y)<BR>　{<BR>　　this.x = x;<BR>　　this.y = y;<BR>　}<BR>　…<BR>}<BR>class Test<BR>{<BR>　static void Main() <BR>　{<BR>　　Point a = new Point();<BR>　　Point b = new Point(3, 4); // 用构造函数初始化对象<BR>　　…<BR>　}<BR>} <BR>　　声明了一个类Point，它提供了两个构造函数。它们是重载的。一个是没有参数的Point构造函数和一个是有两个double参数的Point构造函数。如果类中没有提供这些构造函数，那么会CLR会自动提供一个缺省构造函数的。但一旦类中提供了自定义的构造函数，如Point()和Point(double x, double y)，则缺省构造函数将不会被提供，这一点要注意。<BR>　　3） 静态构造函数<BR>　　静态构造函数是实现对一个类进行初始化的方法成员。它一般用于对静态数据的初始化。静态构造函数不能有参数，不能有修饰符而且不能被调用，当类被加载时，类的静态构造函数自动被调用。如：<BR>using System.Data;<BR>class Employee<BR>{<BR>　private static DataSet ds;<BR>　static Employee()<BR>　{<BR>　　ds = new DataSet(...);<BR>　}<BR>　...<BR>} <BR>　　声明了一个有静态构造函数的类Employee。注意静态构造函数只能对静态数据成员进行初始化，而不能对非静态数据成员进行初始化。但是，非静态构造函数既可以对静态数据成员赋值，也可以对非静态数据成员进行初始化。<BR>　　如果类仅包含静态成员，你可以创建一个private的构造函数：private TestClass() {…}，但是private意味着从类的外面不可能访问该构造函数。所以，它不能被调用，且没有对象可以被该类定义实例化。<BR>　　以上是几种类型构造函数的简单运用，下面将重点介绍一下在类的层次结构中（即继承结构中）基类和派生类的构造函数的使用方式。派生类对象的初始化由基类和派生类共同完成：基类的成员由基类的构造函数初始化，派生类的成员由派生类的构造函数初始化。<BR>　　当创建派生类的对象时，系统将会调用基类的构造函数和派生类的构造函数，构 造函数的执行次序是：先执行基类的构造函数，再执行派生类的构造函数。如果派生类又有对象成员，则，先执行基类的构造函数，再执行成员对象类的构造函数，最后执行派生类的构造函数。<BR>　　至于执行基类的什么构造函数，缺省情况下是执行基类的无参构造函数，如果要执行基类的有参构造函数，则必须在派生类构造函数的成员初始化表中指出。如：<BR>class A<BR>{ private int x;<BR>　public A( ) { x = 0; }<BR>　public A( int i ) { x = i; }<BR>};<BR>class B : A<BR>{ private int y;<BR>　public B( ) { y = 0; }<BR>　public B( int i ) { y = i; }<BR>　public B( int i, int j ):A(i) { y = j; }<BR>};<BR>B b1 = new B(); //执行基类A的构造函数A()，再执行派生类的构造函数B()<BR>B b2 = new B(1); //执行基类A的构造函数A()，再执行派生类的构造函数B(int)<BR>B b3 = new B(0,1); //执行执行基类A的构造函数A(int) ，再执行派生类的&nbsp; <BR>　　构造函数B(int,int) <BR>　　在这里构造函数的执行次序是一定要分析清楚的。另外，如果基类A中没有提供无参构造函数public A( ) { x = 0; }，则在派生类的所有构造函数成员初始化表中必须指出基类A的有参构造函数A(i)，如下所示：<BR>class A<BR>{ private int x;<BR>　public A( int i ) { x = i; }<BR>};<BR>class B : A<BR>{ private int y;<BR>　public B():A(i) { y = 0; }<BR>　public B(int i):A(i) { y = i; }<BR>　public B(int i, int j):A(i) { y = j; }<BR>}; <BR>　　三．析构函数和垃圾回收器在C#中的运用<BR>　　析构函数是实现销毁一个类的实例的方法成员。析构函数不能有参数，不能任何修饰符而且不能被调用。由于析构函数的目的与构造函数的相反，就加前缀‘~’以示区别。<BR>　　虽然C#（更确切的说是CLR）提供了一种新的内存管理机制---自动内存管理机制（Automatic memory management），资源的释放是可以通过“垃圾回收器” 自动完成的，一般不需要用户干预，但在有些特殊情况下还是需要用到析构函数的，如在C#中非托管资源的释放。<BR>　　资源的释放一般是通过"垃圾回收器"自动完成的,但具体来说,仍有些需要注意的地方：<BR>　　1. 值类型和引用类型的引用其实是不需要什么"垃圾回收器"来释放内存的,因为当它们出了作用域后会自动释放所占内存，因为它们都保存在栈(Stack)中;<BR>　　2. 只有引用类型的引用所指向的对象实例才保存在堆(Heap)中,而堆因为是一个自由存储空间,所以它并没有像"栈"那样有生存期("栈"的元素弹出后就代表生存期结束,也就代表释放了内存),并且要注意的是,"垃圾回收器"只对这块区域起作用;<BR>　　然而,有些情况下，当需要释放非托管资源时,就必须通过写代码的方式来解决。通常是使用析构函数释放非托管资源，将用户自己编写的释放非托管资源的代码段放在析构函数中即可。需要注意的是,如果一个类中没有使用到非托管资源,那么一定不要定义析构函数,这是因为对象执行了析构函数,那么"垃圾回收器"在释放托管资源之前要先调用析构函数，然后第二次才真正释放托管资源，这样一来，两次删除动作的花销比一次大多的。下面使用一段代码来示析构函数是如何使用的：<BR>public class ResourceHolder <BR>{<BR>…<BR>~ResourceHolder()<BR>{<BR>　// 这里是清理非托管资源的用户代码段<BR>}<BR>} <BR>　　四．小结<BR>　　构造函数与析构函数虽然是一个类中形式上较简单的函数，但它们的使用决非看上去那么简单，因此灵活而正确的使用构造函数与析构函数能够帮你更好的理解CLR的内存管理机制，以及更好的管理系统中的资源。]]></description>
</item><item>
<title><![CDATA[Visual C#的SQL Server编程]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14347</link>
<author>areyan</author>
<pubDate>2006/5/13 0:48:36</pubDate>
<description><![CDATA[<P>Visual C#的SQL Server编程</P>
<P>Visual Studio.NET的中文Beta 2版本推出已有一段时日了，相比早期的Beta 1版本，新版本各方面都有很大的变化，其中包括SQL Server编程方面，在中文Beta 2中，数据库的存取普遍改用了OLE DB的方式。由于数据库编程是企业级应用开发的核心，本文将举例阐述中文Bete 2版本中的SQL Server编程方法。 </P>
<P>初始设置 </P>
<P>首先，我们需在应用系统中安装SQL Server 2000，Microsoft OLE DB Provider for SQL Server (SQL OLE DB)也会同时被自动安装，接着用SQL Server的Enterprise Manager创建一个叫tyjdb的数据库，并新建一名为address的数据表，其含name、email、age和address四个字段。 </P>
<P>打开VS开发环境中的视图选单项中的服务器资源管理器，该管理器可管理SQL Server及其他各种OLE DB的数据库连接，并可以管理其中的数据。接着我们添加一个新的数据连接，连接属性选择Microsoft OLE DB Provider for SQL server，然后选好服务器及数据库tyjdb，测试连接成功后按确定。使用该工具可又快又准地生成需要的数据库连接字符串。 </P>
<P>连接数据库 </P>
<P>新建一个ASP.NET项目或Windows.NET应用程序，因为二者的数据库存取程序是相同的。将服务器资源管理器中的数据连接拖至新建的Web Form上即可，这时自动生成了一个连接字符串如下： </P>
<P>this.sqlConnection1.ConnectionString<BR>= "data source=WHOAMI;<BR>initial catalog=tyjdb;<BR>integrated security=SSPI;<BR>persist security info=False;<BR>workstation id=WHOAMI;<BR>packet size=4096";<BR>其中WHOAMI为笔者的服务器名。&nbsp; </P>
<P><BR>选取工具箱中的SqlDataAdapter并拖至该Web Form，提示时选取tyjdb的数据连接，选择使用SQL语句访问数据库，生成SQL语句时只填入SELECTFROM ADDRESS，确认完成即可。程序生成代码如下： </P>
<P>protected System.Data.SqlClient.SqlDataAdapter sqlDataAdapter1;<BR>//存取数据库的主要类<BR>protected System.Data.SqlClient.SqlCommand sqlSelectCommand1;<BR>//SQL语句处理的类<BR>protected System.Data.SqlClient.SqlConnection sqlConnection1;<BR>//连接数据库的类<BR>在InitializeComponent()中有如下声明：<BR>this.sqlConnection1 = new System.Data.SqlClient.SqlConnection();<BR>this.sqlDataAdapter1 = new System.Data.SqlClient.SqlDataAdapter();<BR>this.sqlSelectCommand1 = new System.Data.SqlClient.SqlCommand();<BR>this.sqlDataAdapter1.SelectCommand = this.sqlSelectCommand1;<BR>this.sqlSelectCommand1.CommandText = "SELECT name, email, age, address FROM address";<BR>this.sqlSelectCommand1.Connection = this.sqlConnection1;&nbsp; </P>
<P><BR>为使Table中数据能在Web Form中显示，加入一个DataGrid控件至Web Form上，并在Page_Init中加入如下语句： </P>
<P>sqlConnection1.Open();<BR>//打开数据库连接<BR>DataSet objDataset;<BR>//新建一个放数据的DataSet<BR>objDataset=new DataSet();<BR>sqlDataAdapter1.Fill(objDataset, "address");<BR>//将数据填入DataSet<BR>DataGrid1.DataSource=objDataset.Tables["address"].DefaultView;<BR>//关联DataSet和DataGrid<BR>DataGrid1.DataBind();<BR>//绑定数据<BR>sqlConnection1.Close();<BR>//关闭数据库连接&nbsp; </P>
<P><BR>编译执行后Web Form已可将数据库中数据显示在DataGrid中了。 </P>
<P>增加数据 </P>
<P>若想增加数据库数据时，我们只需在Web Form上新增对应字段数量个数的TextBox，并新增一个按键，接着为该按键增加Click事件，具体代码如下： </P>
<P>sqlInsertCommand1.Parameters["@name"].Value=TextBox1.Text;<BR>//将TextBox赋值给对应参数<BR>sqlInsertCommand1.Parameters["@email"].Value=TextBox2.Text;<BR>sqlInsertCommand1.Parameters["@age"].Value=TextBox3.Text;<BR>sqlInsertCommand1.Parameters["@address"].Value=TextBox4.Text;<BR>sqlInsertCommand1.Connection.Open();<BR>//打开连接<BR>sqlInsertCommand1.ExecuteNonQuery();<BR>//执行Insert语句<BR>sqlInsertCommand1.Connection.Close();<BR>//关闭连接<BR>sqlConnection1.Open();<BR>DataSet objDataset;<BR>//下面程序段更新DataGrid<BR>objDataset=new DataSet();<BR>sqlDataAdapter1.Fill(objDataset, "address");<BR>DataGrid1.DataSource=objDataset.Tables["address"].DefaultView;<BR>DataGrid1.DataBind();&nbsp; </P>
<P><BR>执行这段程序时，只需在TextBox中填入要添加的记录字段的值，然后按该按键即可执行添加功能。 </P>
<P>删除数据 </P>
<P>若想删除数据库数据时，我们则需在Web Form上新增一个TextBox5及一个按键，为该按键增加如下代码： </P>
<P>SqlCommand sqlDeleteCommand1 = new System.Data.SqlClient.SqlCommand();<BR>//声明Sql Command类对象<BR>this.sqlDataAdapter1.DeleteCommand = sqlDeleteCommand1;<BR>sqlDeleteCommand1.CommandText="DELETE FROM ADDRESS WHERE NAME='"+TextBox5.Text+"'";<BR>//SQL语句<BR>sqlDeleteCommand1.Connection = this.sqlConnection1;<BR>//声明使用的数据连接<BR>sqlDeleteCommand1.Connection.Open();<BR>sqlDeleteCommand1.ExecuteNonQuery();<BR>//执行该SQL语句<BR>sqlDeleteCommand1.Connection.Close();&nbsp; </P>
<P><BR>执行这段程序时，只需在TextBox5中填入要删除的记录name字段的值，然后按该按键即可执行删除功能。 </P>
<P>更新操作原理都类同，具体开发中可以有许多技巧丰富完善上述程序，如增加错误处理等，这里限于篇幅不一一叙述了。 </P>
<P>综上可知，充分利用Visual Studio.NET的开发环境来简化程序设计对提高编程效率和质量极有好处。 </P>
<P>上述程序均用C#开发，在中文Windows 2000 Server、SQL Server 2000、Visual Studio.NET中文Beta 2环境下，编译并正常运行，中文显示正常。</P>]]></description>
</item><item>
<title><![CDATA[[转]编写高性能 Web 应用程序的 10 个技巧]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14135</link>
<author>areyan</author>
<pubDate>2006/5/6 22:04:04</pubDate>
<description><![CDATA[<FONT size=4>数据层性能&nbsp;<BR>&nbsp;技巧&nbsp;1&nbsp;—&nbsp;返回多个结果集&nbsp;<BR>&nbsp;技巧&nbsp;2&nbsp;—&nbsp;分页的数据访问&nbsp;<BR>&nbsp;技巧&nbsp;3&nbsp;—&nbsp;连接池&nbsp;<BR>&nbsp;技巧&nbsp;4&nbsp;—&nbsp;ASP.NET&nbsp;缓存&nbsp;API&nbsp;<BR>&nbsp;技巧&nbsp;5&nbsp;—&nbsp;每请求缓存&nbsp;<BR>&nbsp;技巧&nbsp;6&nbsp;—&nbsp;后台处理&nbsp;<BR>&nbsp;技巧&nbsp;7&nbsp;—&nbsp;页输出缓存和代理服务器&nbsp;<BR>&nbsp;技巧&nbsp;8&nbsp;—&nbsp;运行&nbsp;IIS&nbsp;6.0（只要用于内核缓存）&nbsp;<BR>&nbsp;技巧&nbsp;9&nbsp;—&nbsp;使用&nbsp;Gzip&nbsp;压缩&nbsp;<BR>&nbsp;技巧&nbsp;10&nbsp;—&nbsp;服务器控件视图状态&nbsp;<BR>&nbsp;小结&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp; 使用&nbsp;ASP.NET&nbsp;编写&nbsp;Web&nbsp;应用程序的简单程度令人不敢相信。正因为如此简单，所以很多开发人员就不会花时间来设计其应用程序的结构，以获得更好的性能了。在本文中，我将讲述&nbsp;10&nbsp;个用于编写高性能&nbsp;Web&nbsp;应用程序的技巧。但是我并不会将这些建议仅局限于&nbsp;ASP.NET&nbsp;应用程序，因为这些应用程序只是&nbsp;Web&nbsp;应用程序的一部分。本文不作为对&nbsp;Web&nbsp;应用程序进行性能调整的权威性指南&nbsp;—&nbsp;一整本书恐怕都无法轻松讲清楚这个问题。请将本文视作一个很好的起点。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 成为工作狂之前，我原来喜欢攀岩。在进行任何大型攀岩活动之前，我都会首先仔细查看指南中的路线，阅读以前游客提出的建议。但是，无论指南怎么好，您都需要真正的攀岩体验，然后才能尝试一个特别具有挑战性的攀登。与之相似，当您面临修复性能问题或者运行一个高吞吐量站点的问题时，您只能学习如何编写高性能&nbsp;Web&nbsp;应用程序。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; <FONT color=#0000ff>我的个人体验来自在&nbsp;Microsoft&nbsp;的&nbsp;ASP.NET&nbsp;部门作为基础架构程序经理的经验，在此期间我运行和管理&nbsp;www.ASP.NET，帮助设计社区服务器的结构，社区服务器是几个著名&nbsp;ASP.NET&nbsp;应用程序（组合到一个平台的&nbsp;ASP.NET&nbsp;Forums、.Text&nbsp;和&nbsp;nGallery）。我确信有些曾经帮助过我的技巧对您肯定也会有所帮助。</FONT><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp; 您应该考虑将应用程序分为几个逻辑层。您可能听说过&nbsp;3&nbsp;层（或者&nbsp;n&nbsp;层）物理体系结构一词。这些通常都是规定好的体系结构方式，将功能在进程和/或硬件之间进行了物理分离。当系统需要扩大时，可以很轻松地添加更多的硬件。</FONT><FONT size=4><FONT color=#0000ff>但是会出现一个与进程和机器跳跃相关的性能下降，因此应该避免。所以，如果可能的话，请尽量在同一个应用程序中一起运行&nbsp;ASP.NET&nbsp;页及其相关组件。<BR><BR>因为代码分离以及层之间的边界，所以使用&nbsp;Web&nbsp;服务或远程处理将会使得性能下降&nbsp;20%&nbsp;甚至更多。<BR></FONT><BR>数据层有点与众不同，因为通常情况下，最好具有专用于数据库的硬件。然而进程跳跃到数据库的成本依然很高，因此数据层的性能是您在优化代码时首先要考虑的问题。<BR><BR>在深入应用程序的性能修复问题之前，请首先确保对应用程序进行剖析，以便找出具体的问题所在。主要性能计数器（如表示执行垃圾回收所需时间百分比的计数器）对于找出应用程序在哪些位置花费了其主要时间也非常有用。然而花费时间的位置通常非常不直观。<BR><BR><FONT color=#0000ff>本文讲述了两种类型的性能改善：大型优化（如使用&nbsp;ASP.NET&nbsp;缓存），和进行自身重复的小型优化</FONT>。这些小型优化有时特别有意思。您对代码进行一点小小的更改，就会获得很多很多时间。使用大型优化，您可能会看到整体性能的较大飞跃。而使用小型优化时，对于某个特定请求可能只会节省几毫秒的时间，但是每天所有请求加起来，则可能会产生巨大的改善。<BR><BR>数据层性能<BR><BR><BR>谈到应用程序的性能调整，有一个试纸性的测试可用来对工作进行优先级划分：代码是否访问数据库？如果是，频率是怎样的？请注意，这一相同测试也可应用于使用&nbsp;Web&nbsp;服务或远程处理的代码，但是本文对这些内容未做讲述。<BR><BR>如果某个特定的代码路径中必需进行数据库请求，并且您认为要首先优化其他领域（如字符串操作），则请停止，然后执行这个试纸性测试。如果您的性能问题不是非常严重的话，最好花一些时间来优化一下与数据库、返回的数据量、进出数据库的往返频率相关的花费时间。<BR><BR>了解这些常规信息之后，我们来看一下可能会有助于提高应用程序性能的十个技巧。首先，我要讲述可能会引起最大改观的更改。<BR><BR>返回页首<BR><FONT color=#ff0000>技巧&nbsp;1&nbsp;—&nbsp;返回多个结果集</FONT><BR><BR><BR>仔细查看您的数据库代码，看是否存在多次进入数据库的请求路径。每个这样的往返都会降低应用程序可以提供的每秒请求数量。通过在一个数据库请求中返回多个结果集，可以节省与数据库进行通信所需的总时间长度。同时因为减少了数据库服务器管理请求的工作，还会使得系统伸缩性更强。<BR><BR>虽然可以使用动态&nbsp;SQL&nbsp;返回多个结果集，但是我首选<FONT color=#0000ff>使用存储过程</FONT>。关于业务逻辑是否应该驻留于存储过程的问题还存在一些争议，但是我认为，如果存储过程中的逻辑可以约束返回数据的话（缩小数据集的大小、缩短网络上所花费时间，不必筛选逻辑层的数据），则应赞成这样做。<BR><BR><FONT color=#0000ff>使用&nbsp;SqlCommand&nbsp;实例及其&nbsp;ExecuteReader&nbsp;方法填充强类型的业务类时，可以通过调用&nbsp;NextResult&nbsp;将结果集指针向前移动</FONT>。图&nbsp;1&nbsp;显示了使用类型类填充几个&nbsp;ArrayList&nbsp;的示例会话。只从数据库返回您需要的数据将进一步减少服务器上的内存分配。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;2&nbsp;—&nbsp;分页的数据访问</FONT><BR><BR><BR>ASP.NET&nbsp;DataGrid&nbsp;具有一个很好的功能：数据分页支持。在&nbsp;DataGrid&nbsp;中启用分页时，一次会显示固定数量的记录。另外，在&nbsp;DataGrid&nbsp;的底部还会显示分页&nbsp;UI，以便在记录之间进行导航。该分页&nbsp;UI&nbsp;使您能够在所显示的数据之间向前和向后导航，并且一次显示固定数量的记录。<BR><BR>还有一个小小的波折。使用&nbsp;DataGrid&nbsp;的分页需要所有数据均与网格进行绑定。例如，您的数据层需要返回所有数据，那么&nbsp;DataGrid&nbsp;就会基于当前页筛选显示的所有记录。如果通过&nbsp;DataGrid&nbsp;进行分页时返回了&nbsp;100,000&nbsp;个记录，那么针对每个请求会放弃&nbsp;99,975&nbsp;个记录（假设每页大小为&nbsp;25&nbsp;个记录）。当记录的数量不断增加时，应用程序的性能就会受到影响，因为针对每个请求必须发送越来越多的数据。<BR><BR><FONT color=#0000ff>要编写性能更好的分页代码，一个极佳的方式是使用存储过程</FONT>。图&nbsp;2&nbsp;显示了针对&nbsp;Northwind&nbsp;数据库中的&nbsp;Orders&nbsp;表进行分页的一个示例存储过程。简而言之，您此时要做的只是<FONT color=#0000ff>传递页索引和页大小。然后就会计算合适的结果集</FONT>，并将其返回。<BR><BR>在社区服务器中，我们编写了一个分页服务器控件，以完成所有的数据分页。您将会看到，我使用的就是技巧&nbsp;1&nbsp;中讨论的理念，从一个存储过程返回两个结果集：记录的总数和请求的数据。<BR><BR>返回记录的总数可能会根据所执行查询的不同而有所变化。例如，WHERE&nbsp;子句可用来约束返回的数据。为了计算在分页&nbsp;UI&nbsp;中显示的总页数，必须了解要返回记录的总数。例如，如果总共有&nbsp;1,000,000&nbsp;条记录，并且要使用一个&nbsp;WHERE&nbsp;子句将其筛选为&nbsp;1000&nbsp;条记录，那么分页逻辑就需要了解记录的总数才能正确呈现分页&nbsp;UI。<BR><BR><BR></FONT><FONT size=4><FONT color=#ff0000>技巧&nbsp;3&nbsp;—&nbsp;连接池<BR></FONT><BR><BR>在&nbsp;Web&nbsp;应用程序和&nbsp;SQL&nbsp;Server&#8482;&nbsp;之间设置&nbsp;TCP&nbsp;连接可能是一个非常消耗资源的操作。Microsoft&nbsp;的开发人员到目前为止能够使用连接池已经有一段时间了，这使得他们能够重用数据库连接。他们不是针对每个请求都设置一个新的&nbsp;TCP&nbsp;连接，而是只在连接池中没有任何连接时才设置新连接。当连接关闭时，它会返回连接池，在其中它会保持与数据库的连接，而不是完全破坏该&nbsp;TCP&nbsp;连接。<BR><BR>当然，您需要小心是否会出现泄漏连接。当您完成使用连接时，请一定要关闭这些连接。再重复一遍：无论任何人对&nbsp;Microsoft.NET&nbsp;Framework&nbsp;中的垃圾回收有什么评论，请一定要在完成使用连接时针对该连接显式调用&nbsp;Close&nbsp;或&nbsp;Dispose。不要相信公共语言运行库&nbsp;(CLR)&nbsp;会在预先确定的时间为您清除和关闭连接。尽管&nbsp;CLR&nbsp;最终会破坏该类，并强制连接关闭，但是当针对对象的垃圾回收真正发生时，并不能保证。<BR><BR>要以最优化的方式使用连接池，需要遵守一些规则。</FONT>
<P><FONT size=4>首先打开连接，执行操作，然后关闭该连接。如果您必须如此的话，可以针对每个请求多次打开和关闭连接（最好应用技巧&nbsp;1），但是不要一直将连接保持打开状态并使用各种不同的方法对其进行进出传递。</FONT></P>
<P><FONT size=4>第二，使用相同的连接字符串（如果使用集成身份验证的话，还要使用相同的线程标识）。如果不使用相同的连接字符串，例如根据登录的用户自定义连接字符串，那么您将无法得到连接池提供的同一个优化值。如果您使用集成身份验证，同时还要模拟大量用户，连接池的效率也会大大下降。尝试跟踪与连接池相关的任何性能问题时，.NET&nbsp;CLR&nbsp;数据性能计数器可能非常有用。<BR><BR>每当应用程序连接资源时，如在另一个进程中运行的数据库，您都应该重点考虑连接该资源所花时间、发送或检索数据所花时间，以及往返的数量，从而进行优化。优化应用程序中任何种类的进程跳跃都是获得更佳性能的首要一点。<BR><BR>应用层包含了连接数据层、将数据转换为有意义类实例和业务流程的逻辑。例如社区服务器，您要在其中填充Forums&nbsp;或&nbsp;Threads集合，应用业务规则（如权限）；最重要的是要在其中执行缓存逻辑。<BR><BR><FONT color=#ff0000>技巧&nbsp;4&nbsp;—&nbsp;ASP.NET&nbsp;缓存&nbsp;API</FONT><BR><BR><BR>编写应用程序代码行之前，一个首要完成的操作是设计应用层的结构，以便最大化利用&nbsp;ASP.NET&nbsp;缓存功能。<BR><BR>如果您的组件要在&nbsp;ASP.NET&nbsp;应用程序中运行，则只需在该应用程序项目中包括一个&nbsp;System.Web.dll&nbsp;引用。<FONT color=#0000ff>当您需要访问该缓存时，请使用&nbsp;HttpRuntime.Cache&nbsp;属性（通过&nbsp;Page.Cache&nbsp;和&nbsp;HttpContext.Cache&nbsp;也可访问这个对象）。<BR></FONT><BR>对于缓存数据，有几个规则。首先，如果数据可能会多次使用时，则这是使用缓存的一个很好的备选情况。第二，如果数据是通用的，而不特定于某个具体的请求或用户时，则也是使用缓存的一个很好的备选情况。如果数据是特定于用户或请求的，但是寿命较长的话，仍然可以对其进行缓存，但是这种情况可能并不经常使用。第三，一个经常被忽略的规则是，有时可能您缓存得太多。通常在一个&nbsp;x86&nbsp;计算机上，为了减少内存不足错误出现的机会，您会想使用不高于&nbsp;800MB&nbsp;的专用字节运行进程。因此缓存应该有个限度。换句话说，您可能能够重用某个计算结果，但是如果该计算采用&nbsp;10&nbsp;个参数的话，您可能要尝试缓存&nbsp;10&nbsp;个排列，这样有可能给您带来麻烦。一个要求&nbsp;ASP.NET&nbsp;的最常见支持是由于过度缓存引起的内存不足错误，尤其是对于大型数据集。<BR><BR><BR>图&nbsp;3&nbsp;ASP.NET缓存<BR><BR><BR>缓存有几个极佳的功能，您需要对它们有所了解。首先，缓存会实现最近最少使用的算法，使得&nbsp;ASP.NET&nbsp;能够在内存运行效率较低的情况下强制缓存清除&nbsp;－&nbsp;从缓存自动删除未使用过的项目。第二，缓存支持可以强制失效的过期依赖项。这些依赖项包括时间、密钥和文件。时间经常会用到，但是对于&nbsp;ASP.NET&nbsp;2.0，引入了一个功能更强的新失效类型：数据库缓存失效。它指的是当数据库中的数据发生变化时自动删除缓存中的项。有关数据库缓存失效的详细信息，请参阅&nbsp;MSDN?Magazine&nbsp;2004&nbsp;年&nbsp;7&nbsp;月的&nbsp;Dino&nbsp;Esposito&nbsp;Cutting&nbsp;Edge&nbsp;专栏。要了解缓存的体系结构，请参阅图&nbsp;3。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;5&nbsp;—&nbsp;每请求缓存</FONT><BR><BR><BR>在本文前面部分，我提到了经常遍历代码路径的一些小改善可能会导致较大的整体性能收益。对于这些小改善，其中有一个绝对是我的最爱，我将其称之为“每请求缓存”。<BR><BR>缓存&nbsp;API&nbsp;的设计目的是为了将数据缓存较长的一段时间，或者缓存至满足某些条件时，但每请求缓存则意味着只将数据缓存为该请求的持续时间。对于每个请求，要经常访问某个特定的代码路径，但是数据却只需提取、应用、修改或更新一次。这听起来有些理论化，那么我们来举一个具体的示例。<BR><BR>在社区服务器的论坛应用程序中，页面上使用的每个服务器控件都需要个性化的数据来确定使用什么外观、使用什么样式表，以及其他个性化数据。这些数据中有些可以长期缓存，但是有些数据却只针对每个请求提取一次，然后在执行该请求期间对其重用多次，如要用于控件的外观。<BR><BR>为了达到每请求缓存，请使用&nbsp;ASP.NET&nbsp;HttpContext。对于每个请求，都会创建一个&nbsp;HttpContext&nbsp;实例，在该请求期间从&nbsp;HttpContext.Current&nbsp;属性的任何位置都可访问该实例。该&nbsp;HttpContext&nbsp;类具有一个特殊的&nbsp;Items&nbsp;集合属性；添加到此&nbsp;Items&nbsp;集合的对象和数据只在该请求持续期间内进行缓存。正如您可以使用缓存来存储经常访问的数据一样，您也可以使用&nbsp;HttpContext.Items&nbsp;来存储只基于每个请求使用的数据。它背后的逻辑非常简单：数据在它不存在的时候添加到&nbsp;HttpContext.Items&nbsp;集合，在后来的查找中，只是返回&nbsp;HttpContext.Items&nbsp;中的数据。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;6&nbsp;—&nbsp;后台处理</FONT><BR><BR><BR>通往代码的路径应该尽可能快速，是吗？可能有时您会觉得针对每个请求执行的或者每&nbsp;n&nbsp;个请求执行一次的任务所需资源非常多。发送电子邮件或者分析和验证传入数据就是这样的一些例子。<BR><BR>剖析&nbsp;ASP.NET&nbsp;Forums&nbsp;1.0&nbsp;并重新构建组成社区服务器的内容时，我们发现添加新张贴的代码路径非常慢。每次添加新张贴时，应用程序首先需要确保没有重复的张贴，然后必须使用“坏词”筛选器分析该张贴，分析张贴的字符图释，对张贴添加标记并进行索引，请求时将张贴添加到合适的队列，验证附件，最终张贴之后，立即向所有订阅者发出电子邮件通知。很清楚，这涉及很多操作。<BR><BR>经研究发现，大多数时间都花在了索引逻辑和发送电子邮件上。对张贴进行索引是一个非常耗时的操作，人们发现内置的&nbsp;System.Web.Mail&nbsp;功能要连接&nbsp;SMYP&nbsp;服务器，然后连续发送电子邮件。当某个特定张贴或主题领域的订阅者数量增加时，执行&nbsp;AddPost&nbsp;功能所需的时间也越来越长。<BR><BR>并不需要针对每个请求都进行电子邮件索引。理想情况下，我们想要将此操作进行批处理，一次索引&nbsp;25&nbsp;个张贴或者每五分钟发送一次所有电子邮件。我们决定使用以前用于对数据缓存失效进行原型设计的代码，这个失效是用于最终进入&nbsp;Visual&nbsp;Studio&reg;&nbsp;2005&nbsp;的内容的。<BR><BR><FONT color=#0000ff>System.Threading&nbsp;命名空间中的&nbsp;Timer&nbsp;类非常有用</FONT>，但是在&nbsp;.NET&nbsp;Framework&nbsp;中不是很有名，至少对于&nbsp;Web&nbsp;开发人员来说是这样。创建之后，这个&nbsp;Timer&nbsp;类将以一个可配置的间隔针对&nbsp;ThreadPool&nbsp;中的某个线程调用指定的回调。这就表示，您可以对代码进行设置，使其能够在没有对&nbsp;ASP.NET&nbsp;应用程序进行传入请求的情况下得以执行，这是后台处理的理想情况。您还可以在此后台进程中执行如索引或发送电子邮件之类的操作。<BR><BR>但是，这一技术有几个问题。如果应用程序域卸载，该计时器实例将停止触发其事件。另外，因为&nbsp;CLR&nbsp;对于每个进程的线程数量具有一个硬性标准，所以可能会出现这样的情形：服务器负载很重，其中计时器可能没有可在其基础上得以完成的线程，在某种程度上可能会造成延迟。ASP.NET&nbsp;通过在进程中保留一定数量的可用线程，并且仅使用总线程的一部分用于请求处理，试图将上述情况发生的机会降到最低。但是，如果您具有很多异步操作时，这可能就是一个问题了。<BR><BR>这里没有足够的空间来放置该代码，但是您可以下载一个可以看懂的示例，网址是&nbsp;www.rob-howard.net。请了解一下&nbsp;Blackbelt&nbsp;TechEd&nbsp;2004&nbsp;演示中的幻灯片和演示。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;7&nbsp;—&nbsp;页输出缓存和代理服务器</FONT><BR><BR><BR>ASP.NET&nbsp;是您的表示层（或者说应该是您的表示层）；它由页、用户控件、服务器控件（HttpHandlers&nbsp;和&nbsp;HttpModules）以及它们生成的内容组成。如果您具有一个&nbsp;ASP.NET&nbsp;页，它会生成输出（HTML、XML、图像或任何其他数据），并且您针对每个请求运行此代码时，它都会生成相同的输出，那么您就拥有一个可用于页输出缓存的绝佳备选内容。<BR><BR>将此行内容添加页的最上端&nbsp;<BR><BR>&lt;%@&nbsp;Page&nbsp;OutputCache&nbsp;VaryByParams="none"&nbsp;Duration="60"&nbsp;%&gt;&nbsp;<BR><BR>就可以高效地为此页生成一次输出，然后对它进行多次重用，时间最长为&nbsp;60&nbsp;秒，此时该页将重新执行，输出也将再一次添加到&nbsp;ASP.NET&nbsp;缓存。通过使用一些低级程序化&nbsp;API&nbsp;也可以完成此行为。对于输出缓存有几个可配置的设置，如刚刚讲到的&nbsp;VaryByParams&nbsp;属性。VaryByParams&nbsp;刚好被请求到，但还允许您指定&nbsp;HTTP&nbsp;GET&nbsp;或&nbsp;HTTP&nbsp;POST&nbsp;参数来更改缓存项。例如，只需设置&nbsp;VaryByParam="Report"&nbsp;即可对&nbsp;default.aspx?Report=1&nbsp;或&nbsp;default.aspx?Report=2&nbsp;进行输出缓存。通过指定一个以分号分隔的列表，还可以指定其他参数。&nbsp;<BR><BR>很多人都不知道何时使用输出缓存，ASP.NET&nbsp;页还会生成一些位于缓存服务器下游的&nbsp;HTTP&nbsp;标头，如&nbsp;Microsoft&nbsp;Internet&nbsp;Security&nbsp;and&nbsp;Acceleration&nbsp;Server&nbsp;或&nbsp;Akamai&nbsp;使用的标头。设置了&nbsp;HTTP&nbsp;缓存标头之后，可以在这些网络资源上对文档进行缓存，客户端请求也可在不必返回原始服务器的情况下得以满足。<BR><BR>因此，使用页输出缓存不会使得您的应用程序效率更高，但是它可能会减少服务器上的负载，因为下游缓存技术会缓存文档。当然，这可能只是匿名内容；一旦它成为下游之后，您就再也不会看到这些请求，并且再也无法执行身份验证以阻止对它的访问了。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;8&nbsp;—&nbsp;运行&nbsp;IIS&nbsp;6.0（只要用于内核缓存）<BR></FONT><BR><BR>如果您未运行&nbsp;IIS&nbsp;6.0&nbsp;(Windows&nbsp;Server?&nbsp;2003)，那么您就错过了&nbsp;Microsoft&nbsp;Web&nbsp;服务器中的一些很好的性能增强。在技巧&nbsp;7&nbsp;中，我讨论了输出缓存。在&nbsp;IIS&nbsp;5.0&nbsp;中，请求是通过&nbsp;IIS&nbsp;然后进入&nbsp;ASP.NET&nbsp;的。涉及到缓存时，ASP.NET&nbsp;中的&nbsp;HttpModule&nbsp;会接收该请求，并返回缓存中的内容。<BR><BR>如果您正在使用&nbsp;IIS&nbsp;6.0，就会发现一个很好的小功能，称为内核缓存，它不需要对&nbsp;ASP.NET&nbsp;进行任何代码更改。当请求由&nbsp;ASP.NET&nbsp;进行输出缓存时，IIS&nbsp;内核缓存会接收缓存数据的一个副本。当请求来自网络驱动程序时，内核级别的驱动程序（无上下文切换到用户模式）就会接收该请求，如果经过了缓存，则会将缓存的数据刷新到响应，然后完成执行。这就表示，当您将内核模式缓存与&nbsp;IIS&nbsp;和&nbsp;ASP.NET&nbsp;输出缓存一起使用时，就会看到令人不敢相信的性能结果。在&nbsp;ASP.NET&nbsp;的&nbsp;Visual&nbsp;Studio&nbsp;2005&nbsp;开发过程中，我一度是负责&nbsp;ASP.NET&nbsp;性能的程序经理。开发人员完成具体工作，但是我要看到每天进行的所有报告。内核模式缓存结果总是最有意思的。最常见的特征是网络充满了请求/响应，而&nbsp;IIS&nbsp;运行时的&nbsp;CPU&nbsp;使用率只有大约&nbsp;5%。这太令人震惊了！当然使用&nbsp;IIS&nbsp;6.0&nbsp;还有一些其他原因，但是内核模式缓存是其中最明显的一个。<BR><BR><FONT color=#ff0000>技巧&nbsp;9&nbsp;—&nbsp;使用&nbsp;Gzip&nbsp;压缩</FONT><BR><BR><BR>虽然使用&nbsp;gzip&nbsp;并不一定是服务器性能技巧（因为您可能会看到&nbsp;CPU&nbsp;使用率的提高），但是使用&nbsp;gzip&nbsp;压缩可以减少服务器发送的字节数量。这就使人们觉得页速度加快了，并且还减少了带宽的用量。根据所发送数据、可以压缩的程度以及客户端浏览器是否支持（IIS&nbsp;只会向支持&nbsp;gzip&nbsp;压缩的客户端发送经过&nbsp;gzip&nbsp;压缩的内容，如&nbsp;Internet&nbsp;Explorer&nbsp;6.0&nbsp;和&nbsp;Firefox），您的服务器每秒可以服务于更多的请求。实际上，几乎每当您减少所返回数据的数量时，都会增加每秒请求数。<BR><BR>Gzip&nbsp;压缩已经内置到&nbsp;IIS&nbsp;6.0&nbsp;中，并且其性能比&nbsp;IIS&nbsp;5.0&nbsp;中使用的&nbsp;gzip&nbsp;压缩要好的多，这是好消息。但不幸的是，当尝试在&nbsp;IIS&nbsp;6.0&nbsp;中打开&nbsp;gzip&nbsp;压缩时，您可能无法在&nbsp;IIS&nbsp;的属性对话中找到该设置。IIS&nbsp;小组在该服务器中置入了卓越的&nbsp;gzip&nbsp;功能，但是忘了包括一个用于启用该功能的管理&nbsp;UI。要启用&nbsp;gzip&nbsp;压缩，您必须深入到&nbsp;IIS&nbsp;6.0&nbsp;的&nbsp;XML&nbsp;配置设置内部（这样不会引起心脏虚弱）。顺便提一句，这归功于&nbsp;OrcsWeb&nbsp;的&nbsp;Scott&nbsp;Forsyth，他帮助我提出了在&nbsp;OrcsWeb&nbsp;上宿主的&nbsp;www.asp.net&nbsp;服务器的这个问题。<BR><BR>本文就不讲述步骤了，请阅读&nbsp;Brad&nbsp;Wilson&nbsp;的文章，网址是&nbsp;IIS6&nbsp;Compression。还有一篇有关为&nbsp;ASPX&nbsp;启用压缩的知识库文章，网址是&nbsp;Enable&nbsp;ASPX&nbsp;Compression&nbsp;in&nbsp;IIS。但是您应该注意，由于一些实施细节，IIS&nbsp;6.0&nbsp;中不能同时存在动态压缩和内核缓存。<BR><BR><BR><FONT color=#ff0000>技巧&nbsp;10&nbsp;—&nbsp;服务器控件视图状态</FONT><BR><BR><BR><FONT color=#0000ff>视图状态是一个有趣的名称，用于表示在所生成页的隐藏输出字段中存储一些状态数据的&nbsp;ASP.NET</FONT>。当该页张贴回服务器时，服务器可以分析、验证、并将此视图状态数据应用回该页的控件树。视图状态是一个非常强大的功能，因为它允许状态与客户端一起保持，<FONT color=#0000ff>并且它不需要&nbsp;cookie&nbsp;或服务器内存即可保存此状态</FONT>。很多&nbsp;ASP.NET&nbsp;服务器控件都使用视图状态来保持在与页元素进行交互期间创建的设置，例如保存对数据进行分页时显示的当前页。<BR><BR>然而使用视图状态也有一些缺点。首先，服务或请求页时，它都会增加页的总负载。对张贴回服务器的视图状态数据进行序列化或取消序列化时，也会发生额外的开销。最后，视图状态会增加服务器上的内存分配。<BR><BR>几个服务器控件有着过度使用视图状态的趋势，即使在并不需要的情况下也要使用它，其中最著名的是&nbsp;DataGrid。ViewState&nbsp;属性的默认行为是启用，但是如果您不需要，则可以在控件或页级别关闭。在控件内，只需将&nbsp;EnableViewState&nbsp;属性设置为&nbsp;false，或者在页中使用下列设置即可对其进行全局设置：&nbsp;<BR><BR>&lt;%@&nbsp;Page&nbsp;EnableViewState="false"&nbsp;%&gt;<BR><BR>如果您不回发页，或者总是针对每个请求重新生成页上的控件，则应该在页级别禁用视图状态。&nbsp;<BR><BR>返回页首<BR>小结<BR><BR><BR>我为您讲述了一些我认为在编写高性能&nbsp;ASP.NET&nbsp;应用程序时有所帮助的技巧。正如我在本文前面部分提到的那样，这是一个初步指南，并不是&nbsp;ASP.NET&nbsp;性能的最后结果。（有关改善&nbsp;ASP.NET&nbsp;应用程序性能的信息，请参阅&nbsp;Improving&nbsp;ASP.NET&nbsp;Performance。）只有通过自己的亲身体验才能找出解决具体性能问题的最好方法。但是，在您的旅程中，这些技巧应该会为您提供一些好的指南。在软件开发中，几乎没有绝对的东西；每个应用程序都是唯一的。<BR><BR>请参阅提要栏“Common&nbsp;Performance&nbsp;Myths”。<BR><BR>Rob&nbsp;Howard&nbsp;是&nbsp;Telligent&nbsp;Systems&nbsp;的创始人，专门从事高性能&nbsp;Web&nbsp;应用程序、知识库管理和协作系统方面的工作。Rob&nbsp;以前受雇于&nbsp;Microsoft，他在那里帮助设计了&nbsp;ASP.NET&nbsp;1.0、1.1&nbsp;和&nbsp;2.0&nbsp;的基础结构。要联系&nbsp;Rob，请访问&nbsp;rhoward@telligentsystems.com。<BR><BR>原文地址：</FONT><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/us0501ASPNETPerformance.mspx" target=_blank><FONT size=4>http://www.microsoft.com/china/msdn/library/we ... us0501ASPNETPerformance.mspx</FONT></A><FONT size=4> </FONT></P>]]></description>
</item><item>
<title><![CDATA[[轉帖]C#.Net三層式開發中的層次劃分討論]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14133</link>
<author>areyan</author>
<pubDate>2006/5/6 21:09:15</pubDate>
<description><![CDATA[<P>&nbsp;&nbsp;&nbsp; 先舉一個曾經在哪本書上看到的例子：現在你想在1米寬的小溪上建一座橋，你會在上面放塊木板就完了。如果想在寬一點的小河上建這橋，你就需要計算木材用料，價格等，如果需要別人幫忙，你還要多一些圖紙什麼的讓別人理解你的想法。現在你要在大江上面建橋，你需要有整體的計畫，包括各個方面，比如將來可能的收費和利益分配等問題。&nbsp; </P>
<P><BR>　　這裏講3層式，其實是針對"大江上面建橋"來的，對於1米寬的小溪，在實際中可能一點用都沒有。不過現在我不可能去拿個長江大橋作例子來講，所以這裏還是用這條簡單的小溪，講講怎麼建橋。之所以講這麼多廢話，是為了防止部分人看完此文之後"小小一個東西，搞那麼麻煩幹什麼。。"其實這裏講的不是具體的這個例子，而是分層的思想，理解這點非常重要。&nbsp; </P>
<P>　　下面我就我們大家日常見最多的例子來講，就是"用戶登錄"的例子。這個例子很簡單，但是麻雀雖小五臟俱全。從資料訪問到業務規則到介面全有了。&nbsp; </P>
<P>　　本文分2個部分，如果只想研究面向物件的思想，對實現已經熟悉，可以跳過第一部分。&nbsp; </P>
<P>第一部分&nbsp; </P>
<P>新建一個空白解決方案。然後：&nbsp; </P>
<P>"添加"－"新建項目"－"其他項目"－"企業級模版項目"－"C#生成塊"－"資料訪問"（資料層，下簡稱D層）&nbsp; </P>
<P>"添加"－"新建項目"－"其他項目"－"企業級模版項目"－"C#生成塊"－"業務規則"（業務層，下簡稱C層）&nbsp; </P>
<P>"添加"－"新建項目"－"其他項目"－"企業級模版項目"－"C#生成塊"－"Web用戶介面"（介面層，下簡稱U層）&nbsp; </P>
<P>右鍵點"解決方案"－"專案依賴項"，設置U依賴於D、C，C依賴於D。&nbsp; </P>
<P>對U添加引用D、C，對C添加引用D。&nbsp; </P>
<P>到此為止，一個三層的架子建立起來了。我上面說的很具體很"傻瓜"，知道的人覺得我廢話，其實我這段時間很強烈的感覺到非常多的人其實對這個簡單的過程完全不瞭解。雖然不反對建2個"空項目"和1個"Asp&nbsp; net&nbsp; Web應用程式專案"也可以作為3層的框架，而且相當多的人認為其實這些"企業級範本專案"其實就是個空項目，這是一個誤區。沒錯，企業級範本專案你從解決方案資源管理器裏看它是個什麼也沒有的，但是你可以用記事本打開專案檔，看見不同了吧？？有些東西在背後，你是看不見的，不過系統已經做好了。也就是說，如果你在C層裏的某個類裏"using&nbsp; System&nbsp; Data&nbsp; SqlClineit"，或者使用一個SqlConnection物件，編譯時候不會出錯，但是會在"任務列表"裏生成一些"策略警告"，警告你在C層裏不要放應該放在D層的東西（雖然就程式來說沒錯，但是可讀性可維護性就打了折扣）而這種功能，空項目是無法給你的。&nbsp; </P>
<P>我們知道建橋需要磚塊，應該是先準備好磚再來建橋，不過為了講解上的順序性和連貫性，簡單性。我們先建橋，建的過程中需要磚塊再現做，這樣就不會多出來"橋不需要的東西"。注意在實際中，還是應該先準備磚塊。&nbsp; </P>
<P>U層其實就是橋，C層是磚塊，D層是原料（石頭、沙子）。這也解釋前面為什麼U層要引用、依賴D層（而不是U對C，C對D的層次），因為橋除了需要磚頭，其實也需要石頭沙子。&nbsp; </P>
<P>我們在U層建一個Login&nbsp; aspx（這裏插入一句，我不喜歡去把系統自動生成的WebForm1&nbsp; aspx拿來改成login或index或直接刪除，我一般留著它當測試代碼用，等到整個系統凍結再把它移除就可以了。）添加1個TextBox（id=txt），一個dropDownList（id=ddl），一個Button(id=btn)。其中dropDownList用來選擇用戶名，button是提交按鈕，&nbsp; TextBox用來輸入密碼。&nbsp; </P>
<P>現在我們必須要添加的代碼分為2部分：&nbsp; 1、Page_load時對ddl的初始化。2、btn的click處理。&nbsp; </P>
<P>1：&nbsp; </P>
<P>private&nbsp; void&nbsp; Page_Load(object&nbsp; sender,&nbsp; System.EventArgs&nbsp; e)&nbsp; </P>
<P>{&nbsp; </P>
<P>if(!IsPostBack)&nbsp; </P>
<P>{&nbsp; </P>
<P><BR>this.ddl.DataSourse=DataManager.GetOneColunm("User","uid");&nbsp; //講解1&nbsp; </P>
<P>this.ddl.DataBind();&nbsp; </P>
<P>}&nbsp; </P>
<P>}&nbsp; </P>
<P>2：&nbsp; </P>
<P>private&nbsp; void&nbsp; Btn_Click(object&nbsp; sender,&nbsp; System.EventArgs&nbsp; e)&nbsp; </P>
<P>{&nbsp; </P>
<P>string&nbsp; uid=this.ddl.selectedValue;&nbsp; </P>
<P>string&nbsp; psw=this.txt.Text;&nbsp; </P>
<P>if(psw&nbsp; ="")&nbsp; </P>
<P>MessageBox("空密碼！");&nbsp; </P>
<P>else&nbsp; </P>
<P>{&nbsp; </P>
<P>User&nbsp; theUser;&nbsp; </P>
<P>try&nbsp; </P>
<P>{&nbsp; </P>
<P>theUser=new&nbsp; User(uid);&nbsp; //講解2&nbsp; </P>
<P>}&nbsp; </P>
<P>catch(Exception&nbsp; e)&nbsp; </P>
<P>{&nbsp; </P>
<P><BR>MessageBox(e.&nbsp; Message);//講解2&nbsp; </P>
<P>return;&nbsp; </P>
<P>}&nbsp; </P>
<P>if(theUser.CheckPsw(psw))&nbsp; //講解3&nbsp; </P>
<P>{&nbsp; </P>
<P>theUser.SetSessions();&nbsp; </P>
<P>Response.Redirect("……………..");&nbsp; //登錄成功！&nbsp; </P>
<P>}&nbsp; </P>
<P>else&nbsp; </P>
<P>{&nbsp; </P>
<P>MessageBox("密碼錯誤！");&nbsp; </P>
<P>}&nbsp; </P>
<P><BR>}&nbsp; </P>
<P>}&nbsp; </P>
<P><BR>講解1：DataManager&nbsp; 是D層中的一個類，提供常見的資料操作。GetOneColunm(string&nbsp; Table,string&nbsp; Colunm)方法返回一個只有1列的DataTable，值為資料庫中表名為Table，的Colunm列。&nbsp; </P>
<P>public&nbsp; class&nbsp; DataManager&nbsp; </P>
<P>{&nbsp; </P>
<P>public&nbsp; DataManager()&nbsp; </P>
<P>{&nbsp; </P>
<P>}&nbsp; </P>
<P>blic&nbsp; static&nbsp; DataTable&nbsp; GetOneColunm(string&nbsp; Table,string&nbsp; Colunm)&nbsp; </P>
<P>{&nbsp; </P>
<P>//此處省略相關代碼。返回指定表指定列&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>其實這個地方演示的是在U層直接繞過C層訪問D層的例子，因為該結構邏輯上很簡單，而且獲取用戶名並不是現實社會中的業務邏輯的一部分（僅僅是介面需要，因為在這裏其實用成2個TextBox的話完全不需要這一步）&nbsp; </P>
<P><BR>講解2：定義一個User類的實例。User類的定義可能如下：&nbsp; </P>
<P><BR>public&nbsp; class&nbsp; User&nbsp; </P>
<P><BR>{&nbsp; </P>
<P><BR>public&nbsp; User(string&nbsp; uid)&nbsp; </P>
<P><BR>{&nbsp; </P>
<P><BR>if(DataManager.IsIn("user","uid=＇"+uid+"＇"))&nbsp; </P>
<P><BR>throw&nbsp; "用戶不存在";&nbsp; </P>
<P><BR>else<BR>//User()其他初始化;&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>public&nbsp; bool&nbsp; CheckPsw(string&nbsp; psw)&nbsp; </P>
<P><BR>{&nbsp; </P>
<P><BR>if(DataManager.IsIn("user","uid=＇"+uid+"＇&nbsp; and&nbsp; psw=＇"+psw+"＇"))&nbsp; </P>
<P><BR>return&nbsp; true;&nbsp; </P>
<P><BR>else&nbsp; </P>
<P><BR>return&nbsp; false;&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>注意到用戶類構造函數中用了個throw來拋出用戶不存在的異常，在下面catch的時候用MessageBox(e.&nbsp; Message);來彈出"用戶不存在"的錯誤。這裏其實也是為了演示一個層間傳遞資訊的手段，異常也是一種手段，雖然在這裏其實可以有其他方式比如返回值，引用參數之類的直接用一個方法來獲得用戶是否存在的資訊，沒必要放在構造裏，我這麼做只是為了演示傳遞過程，在後面的有討論這種用法在分層模式下某種特殊情況的應用以解決一些問題。這個類裏又用了DataManager類的一個靜態方法IsIn(string&nbsp; Table,string&nbsp; str)該方法其實其實是執行&nbsp; "select&nbsp; *&nbsp; from&nbsp; Table&nbsp; where&nbsp; str"&nbsp; </P>
<P><BR>這個Sql語句並在返回空的時候方法返回false，否則返回true。一個很簡單的方法。這裏演示了C層對D層的調用。&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>順便說一句，因為在VS.Net中，項目的名稱會默認地成為項目中的namespace，可以通過把所有自動生成的代碼中的namespace改為"解決方案名稱"來使3個層可以無縫地自由調用。或者在調用的地方using一下其他層的空間名，看個人喜歡了。比如上面的Login.aspx.cs裏需要using2個，而User.cs裏要using一個。&nbsp; </P>
<P><BR>講解3：這裏的檢查用戶密碼同樣用到User類的一個方法CheckPsw（）而這個方法&nbsp; 又用到了IsIn（）這裏就不多說了。&nbsp; </P>
<P><BR>大家注意到我們在U層的頁面裏用MessageBox()方法來彈出對話方塊，其實這個方法寫在PageBase.cs裏，是U層的另外一個檔，繼承Page類，Login類又繼承它，這個方法其實是把Response.Write("")封裝起來了。&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P><BR>到此為止，登錄結束，例子的實現也說完了。不過只講了"然"，沒有講"所以然"。下面開始講"所以然"。&nbsp; </P>
<P><BR>第二部分&nbsp; </P>
<P>&nbsp;</P>
<P><BR>作為對比，我們使用一個不面向物件的，不分層的Asp式的Aspx相同登錄作為對比。具體的Asp代碼我就不寫了，反正登錄哪都有。先來看看他們2者發生的遭遇（這是不幸的，卻偏偏是經常發生的）：&nbsp; </P>
<P><BR>1、&nbsp; 專案經理突然說"不用SqlServer了，換成Access"（正版費用問題）。看看2邊分別發生什麼：3層這邊（A），把DataManager類裏的連接改改（在實際情況下，極可能其實是改它的基類，它本身不用改），Web.config中把字串換掉就完了。Asp式那邊（B），同樣要改Web.config，同樣要改連接什麼的，修改量在這個具體的"小溪"例子上幾乎相同，在"大橋"例子上B應該會稍微多改點，不過也不會多很多。但是！請注意一點，我們在修改代碼的時候，主要時間和精力不是花在"改"這個動作上，而是花在"要改什麼地方"上和"尋找需要改的地方"上。在"大橋"上，B需要花費多的多的時間，對大部分檔進行查找和替換。A則僅僅在資料層裏，另外2個層不需要任何修改。從這個角度出發我們想到2點原則：&nbsp; </P>
<P><BR>a)&nbsp; 資料層必須要能夠保證資料庫的變動（任何結構變動、類型變動）對其餘各層的不透明性。也就是資料庫怎麼變，其他層絕對不應該變哪怕1行代碼！（web.config是整個應用程式的配置，雖然在物理上存在於U層的檔夾中，但個人更願意認為它是獨立的不屬於任何層的，所以這裏不計它）&nbsp; </P>
<P><BR>b)&nbsp; 資料層越小越好（如果沒有這點原則，我們把整個所有的東西都放在資料層，那當然資料庫變動對外面無影響――因為外面幾乎沒東西――但是這顯然不可行）。而且因為前面我們說了，大部分時間花在"找"上面，你小點，找起來也容易點。&nbsp; </P>
<P><BR>2、&nbsp; 客戶突然提出B/S版的不好，要換成C/S版的。對於（B）來說，這是晴天霹靂！！他的所有工作都要重新做，（或者幾乎所有工作），雖然他有很多代碼還可以用，不過他在未來一小段時間就必須不斷在"複製－粘貼"中使用以前的代碼。（A）發生了什麼？？如果你細心看會發現（A）之需要新建個專案"Windows用戶介面"（和前面一樣，添加引用，專案依賴），拖幾個控制項到上面，把控制項名字起成txt，ddl，btn，然後把click代碼和Pageload代碼複製過去，（居然。。。）連1行代碼都不需要修改！！！！當然，這是比較極端的例子（win和web都有TextBox，dropDownList，Button3種控制項，而且我們在PageBase裏定義的方法MessageBox()又剛好和win裏面方法同名。。。）不過儘管有這麼多巧合我們仍然可以也願意相信，在"大橋"上，（A）將比（B）少做很多工作。從這個角度出發我們又想到2點類似原則：&nbsp; </P>
<P><BR>a)&nbsp; 介面層應該保證介面的任何變化都不需要修改其他層的內容（不管這個具體的例子把ddl改為另外一個TextBox，或是把B/S改為C/S）&nbsp; </P>
<P><BR>b)&nbsp; 介面層越小越好（理由同上。）&nbsp; </P>
<P><BR>3、&nbsp; 除開了介面層和資料層，（如果你的方案中只有3個層的話）剩下的就都是邏輯層的內容了。所以和前面的相對應，我們可以得出結論：&nbsp; </P>
<P><BR>a)&nbsp; 邏輯層應當不受資料庫和介面變動的影響而需要修改。&nbsp; </P>
<P><BR>b)&nbsp; 邏輯層越大越好（因為另外2層越小越好。。。）&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>有了最基本的原則，我們應該來討論下，根據原則，要怎麼分層的問題：&nbsp; </P>
<P><BR>1、&nbsp; PageBase.cs&nbsp; 應該放在哪個層？根據上面的原則，應該放在C層。但是實際上我習慣放在U層，或者放在另外一個（第4個層，通用底層，在比資料層還低的位置）層裏。到底放在什麼地方，我最開始的做法是在C層，因為按上面歸納的原則，就應該放在C，但是後來一段時間我習慣於"四層式"之後就把它放在通用底層（下簡稱B層，該層同時也放如本來在D層中的SqlHelper類等，包括原來3層中所有"通用"的類，這裏通用的意思是說其他系統也可以用的到而不需要修改，這個層通常不用解決方案名稱而用公司、小組名稱等作為namespace，在有新專案的時候在建解決方案的時候就可以"添加現有專案"，簡單的加進去並不斷積累，實踐中對提高效率和代碼重用有比較大作用。）不過如果只有3層，我現在傾向於把PageBase放在U層。主要因為最近一段潛心研究面向物件的分析設計的心得。說起來又是一大匹布沒完，不過我又在前面的"原則"上加1條："如果某個類，僅為了某層的某種特殊實現而存在，那麼它必須放在該層"，比如PageBase是為了U層的特殊實現（B/S實現）而存在，又比如SqlHelper是為了D層的特殊實現（SqlServer資料庫）而存在。所以對應的，它們必須分別放在U層和D層（如果不加這條的話按前面他們都該放在C層，因為C層越大越好，而且資料庫和介面的變動不需要改動這2個類－雖然它們可能因改動而沒有用了，不過還是不需要去修改它們）&nbsp; </P>
<P><BR>2、&nbsp; Oldjacky曾經和我談到一個問題：Datagrid中允許作刪除操作，但是如果當前僅餘下最後一條記錄，則不允許這個刪除操作！那麼該刪除應該放在C層還是D層還是U層？我覺得應該從另外一個角度來考慮：&nbsp; </P>
<P><BR>a)&nbsp; 這種"不允許"是"業務規則的不允許"（比如表內的資料表示當前在店裏的職員，刪除表示職員離開店裏－可能去拿貨什麼的，添加表示職員回來，當櫃檯只有一名職員時，顯然他絕對不能離開去送貨），這個時候，此"禁止刪除"的操作應該產生在C層。&nbsp; </P>
<P><BR>b)&nbsp; 這種"不允許"是"程式實現的不允許"（比如當這裏為空的時候會引起其他地方比如ToString()方法產生"未將物件的引用設置到物件的實例……"的錯誤，或程式設計者或專案經理的主觀願望希望它"不允許"以此來減少工作量或簡化程式）。這個時候，此"禁止刪除"可以放在U層（比如上面說的ToString）或D層（比如違反資料庫約束）&nbsp; </P>
<P><BR>3、&nbsp; 細心的人可能會發現，前面的登錄例子裏，用戶一共可以獲得3種彈出錯誤分別是"空密碼""密碼錯誤""用戶不存在"，而其中前2個是在U層裏做的，"用戶不存在"卻是在C層裏做的（我是指這個字串）還是開始說的建橋，我這裏是用"小溪建橋"來講解"大江建橋"所以故意在這裏轉了個沒用的圈，就像在計算小溪上這塊木板到底夠用多少年，其實對小溪沒什麼意義，只是為了講解大橋需要而加上去的，畢竟大橋需要這種考慮。我這裏假設"用戶不存在需要彈出提示"是一種業務邏輯上的需要，而"未輸入密碼需要提示"則不是業務規則需要（比如實際業務中可以允許空密碼，但是專案經理不同意，說一定要密碼）在這個登錄例子中其實根本沒有什麼問題，但是在大項目裏，如果這個東西不是業務規則的需要，就不應該放在業務層，如果是一種業務規則，就要放在業務層。有助於業務模型與現實實體的銜接，也有益於業務邏輯更好地表現現實實體的特徵。&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>到此為止，我再次歸納出我們的最終的原則：&nbsp; </P>
<P><BR>1、&nbsp; 如果某個類，僅為了某層的某種特殊實現而存在，那麼它必須放在該層。&nbsp; </P>
<P><BR>2、&nbsp; 資料層應當在保證資料庫變化對其他層不可見的前提下儘量小。&nbsp; </P>
<P><BR>3、&nbsp; 介面層應當在保證介面變化對業務邏輯層不影響的前提下儘量小。&nbsp; </P>
<P><BR>4、&nbsp; 如果某個類不是業務規則的需要，就不應該放在業務層，反之亦然。&nbsp; </P>
<P><BR>5、&nbsp; 邏輯層應當在保證資料庫或介面變化不會造成自身影響的前提下儘量大。&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>以上5點如果發生衝突，在找平衡點的時候，前面的要高於後面的。比如1和3衝突的時候更傾向於使用規則1。&nbsp; </P>
<P><BR>第二部分結束&nbsp; </P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>有一點應該是"編程代碼習慣"和"面向物件"的範疇，不過因為和分層有些關係，所以也說一下。"如果你的代碼，自己把它翻譯成中文並加必要的標點符號後，其他不懂程式的人看了仍然覺得很亂，那麼你很可能層沒分好"。比如前面的btn的click：&nbsp; </P>
<P><BR>｛&nbsp; </P>
<P><BR>字串&nbsp; 用戶名是&nbsp; 下拉清單&nbsp; 選擇值；&nbsp; </P>
<P><BR>字串&nbsp; 密碼是&nbsp; 輸入框&nbsp; 值；&nbsp; </P>
<P><BR>如果&nbsp; 密碼是&nbsp; 空&nbsp; </P>
<P><BR>對話方塊（密碼空！）；&nbsp; </P>
<P><BR>否則&nbsp; </P>
<P><BR>｛&nbsp; </P>
<P><BR>用戶&nbsp; 這用戶；&nbsp; </P>
<P><BR>嘗試&nbsp; </P>
<P><BR>｛&nbsp; </P>
<P><BR>這用戶&nbsp; 是&nbsp; 新的&nbsp; 用戶（用戶名）；&nbsp; </P>
<P><BR>｝&nbsp; </P>
<P><BR>捕捉（錯誤）&nbsp; </P>
<P><BR>｛&nbsp; </P>
<P><BR>對話方塊（錯誤&nbsp; 消息）；&nbsp; </P>
<P><BR>返回；&nbsp; </P>
<P><BR>｝&nbsp; </P>
<P><BR>如果&nbsp; 這用戶檢查密碼（密碼）&nbsp; </P>
<P><BR>{&nbsp; </P>
<P><BR>這用戶&nbsp; 設置狀態；&nbsp; </P>
<P><BR>回應&nbsp; 重定位（"。。。。。"）；&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>否則&nbsp; </P>
<P><BR>{&nbsp; </P>
<P><BR>對話方塊（密碼錯誤）&nbsp; </P>
<P><BR>}&nbsp; </P>
<P><BR>｝&nbsp; </P>
<P><BR>代碼最好能讓不懂的人也能看懂到底在幹什麼。&nbsp; </P>
<P><BR>最後，oldjacky的Datagrid刪除的例子"刪除"顯然在D層，但是不允許卻可能在C或U，如果在U沒什麼說的了，如果在C，那麼這種"不允許"的一個比較合理的實現方法就是在C層裏遇到這種情況throw一下。當U層裏catch到該throw的時候，股境僮鰨庋?個層同時有原因引起禁止時，可以從代碼一眼看出這種禁止的來源。類似於前面的2種彈出錯誤。<A></A></P>]]></description>
</item><item>
<title><![CDATA[Net开发环境配置[OS/IIS/VS...]]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14132</link>
<author>areyan</author>
<pubDate>2006/5/6 21:02:50</pubDate>
<description><![CDATA[<P>.Net开发环境安装貌视简单,但是,如果有些小细节不注意,却会出现莫名奇妙的错误.<BR>本文主要讲解ASP.NET的配置。水平所限，不足之处还望谅解。</P>
<P>目录<BR>一、ASP.Net需要在什么平台工作？<BR>二、开发平台建议安装步骤<BR>三、IIS的设置<BR>四、操作系统的设置</P>
<P><BR>一、ASP.Net需要在什么平台工作？<BR>1、Win NT 4.0 Workstation&nbsp; + SP6<BR>2、Win NT 4.0 Server +Sp6<BR>3、Win 2000 Professional + sp2<BR>4、Win 2000 Server + SP2<BR>5、Win 2000 Advace Server + sp2<BR>6、Win XP Professional <BR>7、Win 2003任何版本</P>
<P>安装软件包括<BR>1、.Net Framework 1.0&nbsp; 或 1.1 或 2.0<BR>2、MDAC 2.7<BR>3、IIS 5.0<BR>4、IE5.01 或 5.5 或 6.0</P>
<P><BR>二、开发平台建议安装步骤<BR>1、首先安装操作系统(地球人都知道)<BR>2、然后安装驱动程序<BR>3、安装IIS<BR>4、安装SQL SERVER<BR>5、安装VS</P>
<P>注意：<BR>第一步，安装操作系统要求硬盘格式为NTFS(C盘)，我记得我以前安装的不是 NTFS的好象运行不了，C盘空间建议7G以上<BR>第三步，安装IIS的时候应该选中FrontPage 2000扩展,这个是VS创建工程的时候需要使用的<BR>第四步，安装SQL SERVER应该采用sa方式登陆，而不是Windows系统的</P>
<P>三、IIS的设置<BR>在站点属性中，网站选项卡/IP地址 保持(全部未分配)<BR>保证每个站点，虚拟目录的 目录安全性选项卡/编辑/匿名访问和集成Windows登陆都要选中。<BR>如果出现错误，尝试把主目录选项卡中，应用程序设置，删除一下，然后再创建。(如果原本就不是应用程序,那么直接创建).</P>
<P>1、IIS在2000，2003等服务器操作系统的特殊设置<BR>在服务器系统中本来也没什么特殊设置，但是如果要装1.1和2.0的混合环境的话那么就要注意了。同时安装1.1和2.0的.net框架将会产生冲突。一般导致某个站点在10-15分钟内无法访问。原因，服务关闭。<BR>出现这种错误是因为在服务器系统中存在应用程序连接池，它的作用是提供给你设置垃圾回收的处理方案。但是1.1和2.0如果同时使用一个应用程序连接池，那么就会产生冲突。</P>
<P>解决办法：<BR>把1.1和2.0分别放在不同的应用程序连接池中，建立站点或者虚拟目录的时候把主目录选项卡中，应用程序设置/应用程序连接池选中成对应的版本的应用程序连接池，在ASP.NET选项卡中选择应用程序的版本。</P>
<P>四、操作系统的设置<BR>1、在2000，2003等服务器操作系统的设置<BR>在服务器系统中要注意文件写入权限的设置，因为默认访问应用程序的系统用户为Internet 来宾帐户，权限很低，是GUEST组的。特别是使用ACCESS数据库的情况。</P>
<P>2、在XP操作系统中的设置<BR>最好把Internet 来宾帐户，设置成Administrators组，如果你要使用ACCESS数据库的话。</P>
<P>另外强烈建议关闭 索引服务。</P>]]></description>
</item><item>
<title><![CDATA[提高SQL效率]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14066</link>
<author>areyan</author>
<pubDate>2006/5/4 21:52:19</pubDate>
<description><![CDATA[<SPAN class=spnMessageText id=msg><FONT color=#191970 size=2>避免LEFT JOIN 和 NULL <BR><BR><BR>當然，有很多時候您需要執行LEFT JOIN 和使用 NULL 值。但是，它們並不適用於所有情況。改變 SQL 查詢的構建方式可能會#29987;生將一個花幾分鐘運行的報告縮短到只花幾秒鐘這樣的天壤之別的效果。有時，必須在查詢中調整資料的形態，使之適應應用程式所要求的顯示方式。雖然 TABLE 資料類型會減少大量佔用資源的情況，但在查詢中還有許多區域可以進行優化。SQL 的一個有價值的常用功能是 LEFT JOIN。它可以用於檢索第一個表中的所有行、第二個表中所有匹配的行、以及第二個表中與第一個表不匹配的所有行。例如，如果希望返回每個客戶及其定單，使用 LEFT JOIN 則可以顯示有定單和沒有定單的客戶。<BR><BR>此工具可能會被過度使用。LEFT JOIN 消耗的資源非常之多，因#29234;它們包含與 NULL（不存在）資料匹配的資料。在某些情況下，這是不可避免的，但是代價可能非常高。LEFT JOIN 比 INNER JOIN 消耗資源更多，所以如果您可以重新編寫查詢以使得該查詢不使用任何 LEFT JOIN，則會得到非常可觀的回報。 <BR><BR>加快使用LEFT JOIN 的查詢速度的一項技術涉及創建一個 TABLE 資料類型，插入第一個表（LEFT JOIN 左側的表）中的所有行，然後使用第二個表中的值更新 TABLE 資料類型。此技術是一個兩步的過程，但與標準的 LEFT JOIN 相比，可以節省大量時間。一個很好的規則是嘗試各種不同的技術並記錄每種技術所需的時間，直到獲得用於您的應用程式的執行性能最佳的查詢。 <BR><BR>測試查詢的速度時，有必要多次運行此查詢，然後取一個平均值。因#29234;查詢（或存儲過程）可能會存儲在SQL Server 記憶體中的過程緩存中，因此第一次嘗試耗費的時間好像稍長一些，而所有後續嘗試耗費的時間都較短。另外，運行您的查詢時，可能正在針對相同的表運行其他查詢。當其他查詢鎖定和解鎖這些表時，可能會導致您的查詢要排隊等待。例如，如果您進行查詢時某人正在更新此表中的資料，則在更新提交時您的查詢可能需要耗費更長時間來執行。 <BR><BR>避免使用LEFT JOIN 時速度降低的最簡單方法是盡可能多地圍繞它們設計資料庫。例如，假設某一#29987;品可能具有類別也可能沒有類別。如果 Products 表存儲了其類別的 ID，而沒有用於某個特定#29987;品的類別，則您可以在欄位中存儲 NULL 值。然後您必須執行 LEFT JOIN 來獲取所有#29987;品及其類別。您可以創建一個值#29234;“No Category”的類別，從而指定外鍵關係不允許 NULL 值。通過執行上述操作，現在您就可以使用 INNER JOIN 檢索所有#29987;品及其類別了。雖然這看起來好像是一個帶有多餘資料的變通方法，但可能是一個很有價值的技術，因#29234;它可以消除 SQL 批次處理語句中消耗資源較多的 LEFT JOIN。在資料庫中全部使用此概念可以#29234;您節省大量的處理時間。請記住，對於您的用戶而言，即使幾秒鐘的時間也非常重要，因#29234;當您有許多用戶正在訪問同一個聯機資料庫應用程式時，這幾秒鐘實際上的意義會非常重大。</FONT><BR></SPAN>]]></description>
</item><item>
<title><![CDATA[提高VB访问数据库的效率]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14065</link>
<author>areyan</author>
<pubDate>2006/5/4 21:49:13</pubDate>
<description><![CDATA[<A>　
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">1.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">尽量使用事务处理更新数据库</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的事务处理包括以</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">BeginTrans</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">开始，以</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">CommitTrans</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">或</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Rollback</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">结尾的多条数据库操作指令。事务处理除了能很好的保证数据库的完整性以外，同时能大大提高数据库批量更新的效率。这是因为如果数据库更新操作没有使用事务处理，则每次</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Update</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">操作都会引起数据库写盘一次。使用事务处理后，更新只在内存缓冲区内进行，执行</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">CommitTrans</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">时才将所有修改一次写回到磁盘中。使用事务处理要注意一下几点</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">:</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><FONT face="Times New Roman"><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> </SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">(1)</SPAN></FONT><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">事务处理要有很完善的错误检查机制</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">;</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><FONT face="Times New Roman"><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> </SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">(2)</SPAN></FONT><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">因为</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">在事务处理结束前对数据库使用了页面锁</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">所以在多用户环境中，如果事务被挂起，则其它用户将无法访问上锁的数据。</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> <o:p></o:p></FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">2.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">尽量使用代码分解</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Select</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">检索操作</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> <o:p></o:p></FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Select</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">进行数据库操作固然简单易用，但如果将一些检索操作分解为等价的手工检索代码，则对数据库的检索速度将大大加快</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">分解的基本方法是对检索关键字段进行索引，利用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Seek</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">方法定位后，根据索引的数据库已经排序的特点，进行遍历查找</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">对于遍历范围不是很宽时，这种方法能几十倍的提高数据库的访问速度</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">例如</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">:Select * from person where vol= '123' and birth= #11-02-73# </FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">分解成下面的操作后，访问速度可大大提高：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Table.Index= "vol"</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Table.Seek "="</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">"123"</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">if not table.nomatch then</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">while not table.eof</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> if table("vol")="123" then</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> table.movelast</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> else if table("Birth")= #11-02-73# then</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> '</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">找到记录</SPAN><FONT face="Times New Roman"><SPAN lang=ZH-CN> </SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> end if</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> table.movenext</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">wend</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT face="Times New Roman"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">end if</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">3.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">attach</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">绑定数据库表</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> <o:p></o:p></FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　当使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">ODBC</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">连接</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">MS SQL Server</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Oracle</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Sysbase</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">之类的数据库服务器时，我们可以通过</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">MS Acess</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">attach</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">功能将服务器上的表绑定到</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">MS Acess</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">数据库中，因为</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">MS Acess</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">数据库能缓存数据库服务器上表的结构，当我们访问</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">ODBC</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">数据源时能提高系统的访问性能。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">4.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">dbSQLPassThrough</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">选项</SPAN><SPAN lang=EN-US><FONT face="Times New Roman"> <o:p></o:p></FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　连接</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">MS SQL Server</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> Oracle</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Sysbase</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">数据库服务器时，使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">dbSQLPassThrough</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">选项可将命令直接发送给数据库服务器，从而减少中间件对命令的检查和解释，提高了数据库的访问性能。下例使用存储过程建立</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Dynaset:</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><FONT face="Times New Roman"><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> </SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">dim mydb as databasedim myds as dynasetset mydb=opendatabase(..........)'</SPAN></FONT><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">打开数据库</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">set myds=mydb.openrecordset("name"</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">dbOpendynaset</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">dbSQLPassThrough</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">...)</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> </FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">dbSQLPassThrough</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的缺点是返回的记录集是只读的。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">5.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">正确使用数据库访问对象</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Table.</SPAN><SPAN lang=EN-US> <o:p></o:p></SPAN></FONT></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　支持</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">SEEK</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">命令和索引</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">两者配合能最快的找到纪录</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">笔者曾经做过速度比较试验，都是检索</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">10</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">万个记录</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Table </FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">用时</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">3.5</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">秒</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Dynaset </FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">用时</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">9</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">秒</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Snapshot</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">用时</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">10</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">秒</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">支持读写操作</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不支持</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">SORT</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">FILTER</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，必须使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Index</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">代替</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">对应于数据库中的物理表，增，删，改会直接影响数据库表。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><FONT face="Times New Roman"><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"> </SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Dynaset.</SPAN></FONT><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">最灵活的数据库对象</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">支持读写操作，是记录的动态子集</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">在</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">ODBC</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">中，写操作需要设定唯一性索引</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">支持</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">SORT</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">FILTER.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">JOIN</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">命令关联多个表时，只能使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Dynaset</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman"><FONT size=3>&nbsp;<o:p></o:p></FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">　　</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> Snapshot.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">只能读不能写，不能加锁</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不支持事务处理</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">.</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不支持</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Edit</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Addnew</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Update</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">方法</SPAN></FONT></P></A>]]></description>
</item><item>
<title><![CDATA[面向对象在VB6语言中的应用]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14064</link>
<author>areyan</author>
<pubDate>2006/5/4 21:45:58</pubDate>
<description><![CDATA[
<H1 style="MARGIN: 9pt 0cm; TEXT-ALIGN: center" align=center><FONT size=4><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">面向对象在</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face=Arial>VB6</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">语言中的应用</SPAN></FONT></H1>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-FAMILY: 新細明體"><FONT size=3>&nbsp;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">来公司之前</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">没接触过</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">，只知道和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Delphi</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">一样，是一个优秀的</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">RAD</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">开发工具，但和</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">Delphi</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">强大的面向对象能力不同的是，</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">不支持面向对象的功能</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">属于传统的</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">RAD</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">开发工具。最初对</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的感觉就是这样的，肤浅而又片面，在公司使用</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的这段时间内，越来越发现当初对</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">的认识有失偏颇，面向对象的几个重要特点，基本上都可以在</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB6</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">实现。这篇文章，一方面是对我自己当初对</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">错误认识的一个纠正，加深自己对</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">VB</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">中面向对象功能的认识。更重要的一个原因是：希望这篇文章能起拋砖引玉的作用，使得部门同事之间在信息交流，技术共享方面做得更好。毕竟思想的分享具有传递和累加性，交流和探讨的过程，也是加深理解，纠正错误观点，清晰思路，提高自己的过程。好了，闲话少说，让我们进入正题</SPAN><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">!</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></FONT></FONT></P>
<H3 style="MARGIN: 0cm 0cm 0pt"><FONT size=5><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">一：面向对象</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face=Arial>(Object-Oriente)</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">编程的基本概念</SPAN></FONT></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">什么是面向对象编程呢？首先</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">面向对象编程与结构化编程相对而言，是结构化编程语言发展到一定阶段，无法解决软件规模越来越大而出现的软件危机，在其基础上形成的。结构化编程是一种编程方法，是用计算器的视角来抽象问题的方法，关注的是特定问题的具体业务流程</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">面向对象编程也是一种编程方法，它采用从更接近真实世界的视角来分析问题，使用更接近人们理解真实世界的方法来抽象问题，仿真真实世界的方法，这种方法称为“面向对象”</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">(OO)</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">。</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">面向对象的本质是对真实世界的抽象与仿真，把要解决的问题如业务逻辑抽象成一个个的业务模型</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">业务的流向和逻辑通过业务模型的交互来进行处理和分析。类与对象是面向对象编程中最基本的两个概念。类是对真实世界事物的仿真和抽象，在编程中可以认为是自己定义的数据结构，拥有自己的方法和数据成员，其中数据成员表示类对象的状态，而方法是改变类状态的操作。对象是类的具体实现。类是个概念，而对象是这个概念的实体。一个完全的面向对象的语言，至少要具备以下四个最基本的特征。</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">1</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：抽象</SPAN><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> </FONT></SPAN></FONT><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: Arial; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Abstract</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">2</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：封装</SPAN><SPAN lang=ZH-CN style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> </FONT></SPAN></FONT><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: Arial; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Encapsulation</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">3</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：继承</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"> Inherited</FONT></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 48.75pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">4</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：多态</SPAN></FONT><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: Arial; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun">Polymorphism</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0; mso-char-indent-size: 12.0pt; tab-stops: 96.75pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">1</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：抽象</SPAN></FONT><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：抽象是对现实生活中相同类别事物的共有特征的高度概括。或许这样的解释比较枯燥</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">，也不容易理解。前面提到，面向对象是对现实生活事物的仿真和真实反映，那就以现实中的例子加以说明。想象一下鸟儿的形象，不用特定指哪一种鸟，只要是说到鸟这样概念，在脑海中基本上就会出现如下的一个形象：有翅膀，有羽毛，有两只脚，会飞，会唱歌的精灵。为什么说到鸟我们就自然想到是这样的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">而不是一个头上有角，身躯庞大，有四只脚的牛的模样呢？这是因为有翅膀，有羽毛，有两只脚，会飞，会唱歌是现实世界中各种各样鸟的共同的特征</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">这样的共同特征就是对鸟最生动的抽象。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">由此可见，抽象的目的是为了提取共性，明确数据成员，清晰功能和方法。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">抽象是面向对象建模中最基本的要求，在实际的程序设计对特定领域的业务建模时，一个适合的抽象能对建模的成功起到事半功倍的效果。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">2</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：封装。封装是隐藏内部实现细节，只向外公布特定的访问接口，减少操作的复杂性。封装的目的是为了信息隐藏。比如天天使用的显视器，有打开</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">/</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">关闭按钮，通过这个按钮，就可以实现打开和关闭显示屏的目的，对于使用者来说，需要的是通过这样的简单按钮就可以操作显示器，根本不需要关心显示屏的内部是如何通过这个按钮真正实现对显示屏的打开和关闭的工作。这是现实中的封装。面向对象中的封装主要的作用也在于些：隐藏实现细节，实现代码的安全性。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">3</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：继承。继承的含义是父类拥有的特征和功能，子类可以自动拥有。继承的目的是为用代码重用，缩短编码时间，减少开发周期。世界万物中，存在着许多生动的现象来告诉我们什么是继承，比如说鸟的一种：百灵鸟，因为属于鸟这个类别，就自然拥有鸟儿有翅膀，有羽毛，可以飞翔，可以歌唱的本领。俗话中的“虎父无犬子</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">”,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">“老鼠的儿子会打洞”等等，都是在用通俗但很精辟的语言阐述着什么是继承。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>4</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：多态。多态是面向对象语言中最难理解的概念，事实上也是使用最广泛的一个特性。从字面意义来理解，多态就是一个对象具有多种形态。从程序实现上来看，多态是父类通过调用不同子类的相同方法，实现不同子类相同的操作，达到不同的效果，产生出不同的形态。还是以刚才的例子来说明吧，百灵是鸟的一种，黄鹂也是鸟的一种。它们都有由父亲继承下来的动作：歌唱。但百灵歌声清脆悦耳，黄鹂歌声婉转动人。同样的一个动作，不同的鸟儿会唱出不同的旋律，但我们都可以说是鸟儿在歌唱。这就是生活中的多态。正是存在着各种各样的多态，窗外的世界才会如此多姿多彩，耳边才时时响起醉人的燕语莺声。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<H3 style="MARGIN: 0cm 0cm 0pt"><FONT size=5><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">二：</SPAN><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face=Arial>VB6</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN">中的面向对象应用</SPAN></FONT></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">初步了解了面向对象的基本概念后，现在我们来看看，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中面向对象三大特征的实现和应用。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman">1</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：封装</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">封装应该是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中用得最多的面向对象的概念。封装在面向对象语言中常表现为：属性，方法和事件。属性应该是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中实现封装最多的一种，具体实现很简单，定义好一个私有变量，再定义好相应的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Let </SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"> Get </SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">属性</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"> </SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">就可以实现榜上相应的属性。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Get</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Let</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">分别对应着对这个属性的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Read(</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">读</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">) </SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"> Write (</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">写</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">)</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">相关方法如下：</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT size=3><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>Private sSomeValue As String</FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>Public Property Let SomeValue( Byval vData as string)</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>sSomeValue = vData</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>End Property</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT size=3><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>Public Property Get SomeValue() As String</FONT></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>SomeValue = sSomeValue</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>End Property</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">2: </SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">继承</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 169.5pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN>VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中通过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">implentments</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">关键词来实现继承。要注意的是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">在</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中指定继承后，对于父类所公开的的属性和方法，必须要手动在子类中一个一个的实现。当然如果觉得手动编码不方便的话，也可以通过</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">IDE</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">ClassBuilder</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">类生成器帮助也可以。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 169.5pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">但有点奇怪的是，在</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中，子类从父类那继承的，只能是接口，而不能继承父类中的实现。就算是接口，也要在前面加上父类的名称才可以正确编译。这样看来，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中的继承，实际上只能算得上的面向接口继承，而不能称为面向实现继承了。面向实现继承是可复用的基础，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">提供的只是接口继承，无法提供实现继承，再加上也不能实现重载</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">(override)</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">和过载</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">(overload)</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">的功能，这些可能是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中面向对象无法得到广泛使用的原因之一吧</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 169.5pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">3</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：多态</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">相对于继承支持的不足</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">, VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">对多态的实现是很成功。仔细思考后也就清楚了其中的原因，多态的实质是接口与实现分离</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">父类定义接口，子类实现接口。而</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中的继承恰恰实现的就是面向接口继承，所有的实现都必须在子类中完成。表现出的正是多态的特征。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">由于</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">中无法实现面向实现继承</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">再加上访问修饰符只有</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Private</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">和</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Public</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">两种</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">没有针对继承的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Protected</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">。所以</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB6</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">应该不能称上是真正的面向对象语言。幸运的是，在</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">DotNet</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">环境下，</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">VB.Net</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">实现了以上的所有不足，成为一个真正的面向对象语言。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<H3 style="MARGIN: 0cm 0cm 0pt"><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: Arial; mso-hansi-font-family: Arial; mso-fareast-language: ZH-CN"><FONT size=5>三：让我们看得更得更深入点</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=3><SPAN lang=EN-US style="mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun"><FONT face="Times New Roman"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>1</FONT></SPAN><SPAN lang=ZH-CN style="FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN">：封装变化</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">封装的目的是实现信息隐藏，简化访问操作。但要明确的是，封装的对象是什么？或许大家都有过这样的开发体会，在开发过程中，有时需求的一点变更会引起多处程序的修改，严重时会因为一个小小的修改而导致好多意想不到的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Bug</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">。用户的需求可能千变万化，理想的情况当然是在系统分析中把所有的业务逻辑和情况都考虑到，但业务发展无法预见，再完美的系统设计也无法解决未知的业务发展变化。而程序开发参考的是现有的项目设计文文件和开发文档，所以业务的变更结果是程序修改无法避免。那么如何做到程序设计中在满足新的需求变化的同时，尽可能减少修改呢？现实中的封装或许可以帮助我们找到部分答案：显示器通过连接线与</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">PC</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">主机通讯，实现正常工作。以前使用的是</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">15’</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">显示器，然后发展成</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">17’</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">纯平</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">现在流行液晶了。但对于主机来说，不论显示器的类型如何变换，大小如何改变，形状如何变幻，但只要显示器提供的连接线结构不变，主机就不用做任何的改动，继续通过显示接口与显示器正常通讯。看，多么简单但又高效的设计，解决了人们对显示器要求的不断更新。在程序设计中，我们也可以学习这样的思想来解决不断出现的需求变化：封装变化，将存在变化的业务逻辑封装成一个或多个独立的类，提供相应的功能接口供外部程序使用。但业务规则发生改变时，只须修改封装这一业务逻辑的类，将修改所引起变更的范围压缩到最小。只要对外的接口函数没有改变，外部与这个类交互的代码就不用做任何修改，自然就不用担心程序中其它代码会因为这次的修改而产生更多的</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt">Bug</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">2</FONT></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">：状态维护</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">面向对象的封装的目的是为了信息隐藏</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">提供代码访问的安全性。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">对于一个类来说，封装的结果对外表现为属性和方法。其中属性是类状态表现</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><FONT face="Times New Roman">,</FONT></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">而方法表现出来是类能实现的功能和操作。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">类属性与全局变量是有区别的，在程序运行时，同一时间内，全局变量只能有一个值，程序中所有访问该全局变量的代码，得到的是相同一个值。属性不同，类在程序运行时必须要实例化成具体的对象才能工作，所有实例化的对象都有相同的属性，但每一个对象的属性值都可能不同。每一个不同的属性值都可以看成是同一个类同一属性不同状态的表现。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">&nbsp;<o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 11pt; mso-char-indent-count: 1.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>3:</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">面向接口继承和面向实现继承</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 96.75pt"><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 12.0pt"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt">面向基类继承也就是面向实现继承，表现出的是子类自动拥有父类的特征，自然界的遗传特性基本上都可以看成是典型的面向基类继承。那么面向接口继承该怎么理解呢？我们可以把接口理解成是一系列概括性规范和标准，还没有做定具体的规则。不同的实现者可以按照自己的实际情况去填充和实现。</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 12.0pt"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0; mso-char-indent-size: 11.0pt; tab-stops: 96.75pt"><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 9.0pt">举个例子</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 9.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 9.0pt">一老汉</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 9.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 9.0pt">做了一个面饼</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 9.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMILY: SimSun; mso-ascii-font-family: 新細明體; mso-hansi-font-family: 新細明體; mso-fareast-language: ZH-CN; mso-bidi-font-size: 9.0pt">给了他的几个儿子</SPAN><SPAN lang=EN-US style="FONT-SIZE: 11pt; FONT-FAMILY: 新細明體; mso-fareast-language: ZH-CN; mso-fareast-font-family: SimSun; mso-bidi-font-size: 9.0pt">,</SPAN><SPAN lang=ZH-CN style="FONT-SIZE: 11pt; FONT-FAMI]]></description>
</item><item>
<title><![CDATA[搞返咪部机啦！]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14046</link>
<author>areyan</author>
<pubDate>2006/5/3 19:29:55</pubDate>
<description><![CDATA[今日终于重装好部机，装返好D软件，以后每个星期返来就可以编下程啦！]]></description>
</item><item>
<title><![CDATA[摄像头编程（转）]]></title>
<link>http://blogger.org.cn/blog/more.asp?name=areyan&amp;id=14031</link>
<author>areyan</author>
<pubDate>2006/5/2 22:09:32</pubDate>
<description><![CDATA[<DIV>
<P>这段时间搞视频采集方面的程序，在国外网站上找到一个用C#写的驱动摄像头的程序。</P>
<P>经改造和调试，如下：</P>
<P>安装摄像头后，一般可以找到一个avicap32.dll文件</P>
<P>这是一个关于设想头的类</P></DIV>
<DIV>using System;<BR>using System.Runtime.InteropServices;<BR>namespace webcam<BR>{<BR>/// <BR>/// avicap 的摘要说明。<BR>/// <BR>public class showVideo<BR>{<BR>// showVideo calls<BR>[DllImport("avicap32.dll")] public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);<BR>[DllImport("avicap32.dll")] public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);<BR>[DllImport("User32.dll")] public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam); <BR>[DllImport("User32.dll")] public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam); <BR>[DllImport("User32.dll")] public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam); <BR>[DllImport("User32.dll")] public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);<BR>[DllImport("User32.dll")] public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);<BR>[DllImport("avicap32.dll")]public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize );</DIV>
<DIV>&nbsp;</DIV>
<DIV>// Constants<BR>public const int WM_USER = 0x400;<BR>public const int WS_CHILD = 0x40000000;<BR>public const int WS_VISIBLE = 0x10000000;<BR>public const int SWP_NOMOVE = 0x2;<BR>public const int SWP_NOZORDER = 0x4;<BR>public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;<BR>public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;<BR>public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;<BR>public const int WM_CAP_SET_PREVIEW = WM_USER + 50;<BR>public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;<BR>public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;<BR>&nbsp;<BR>// Structures<BR>[StructLayout(LayoutKind.Sequential)] public struct VIDEOHDR<BR>{<BR>[MarshalAs(UnmanagedType.I4)] public int lpData;<BR>[MarshalAs(UnmanagedType.I4)] public int dwBufferLength;<BR>[MarshalAs(UnmanagedType.I4)] public int dwBytesUsed;<BR>[MarshalAs(UnmanagedType.I4)] public int dwTimeCaptured;<BR>[MarshalAs(UnmanagedType.I4)] public int dwUser;<BR>[MarshalAs(UnmanagedType.I4)] public int dwFlags;<BR>[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public int[] dwReserved;<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>[StructLayout(LayoutKind.Sequential)] public struct BITMAPINFOHEADER<BR>{<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biSize ;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biWidth ;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biHeight ;<BR>[MarshalAs(UnmanagedType.I2)] public short biPlanes;<BR>[MarshalAs(UnmanagedType.I2)] public short biBitCount ;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biCompression;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biSizeImage;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biXPelsPerMeter;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biYPelsPerMeter;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biClrUsed;<BR>[MarshalAs(UnmanagedType.I4)] public Int32 biClrImportant;<BR>} </DIV>
<DIV>&nbsp;</DIV>
<DIV>[StructLayout(LayoutKind.Sequential)] public struct BITMAPINFO<BR>{<BR>[MarshalAs(UnmanagedType.Struct, SizeConst=40)] public BITMAPINFOHEADER bmiHeader;<BR>[MarshalAs(UnmanagedType.ByValArray, SizeConst=1024)] public Int32[] bmiColors;<BR>}<BR>&nbsp;<BR>public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);<BR>&nbsp;<BR>// Public methods<BR>public static object GetStructure(IntPtr ptr,ValueType structure)<BR>{<BR>return Marshal.PtrToStructure(ptr,structure.GetType());<BR>}<BR>&nbsp;<BR>public static object GetStructure(int ptr,ValueType structure)<BR>{<BR>return GetStructure(new IntPtr(ptr),structure);<BR>}<BR>&nbsp;<BR>public static void Copy(IntPtr ptr,byte[] data)<BR>{<BR>Marshal.Copy(ptr,data,0,data.Length);<BR>}<BR>&nbsp;<BR>public static void Copy(int ptr,byte[] data)<BR>{<BR>Copy(new IntPtr(ptr),data);<BR>}<BR>&nbsp;<BR>public static int SizeOf(object structure)<BR>{<BR>return Marshal.SizeOf(structure); <BR>}<BR>}<BR>//Web Camera Class<BR>public class WebCamera<BR>{<BR>// Constructur<BR>public WebCamera(IntPtr handle, int width,int height)<BR>{<BR>mControlPtr = handle;<BR>mWidth = width;<BR>mHeight = height;<BR>}<BR>&nbsp;<BR>// delegate for frame callback<BR>public delegate void RecievedFrameEventHandler(byte[] data);<BR>public event RecievedFrameEventHandler RecievedFrame;<BR>&nbsp;<BR>private IntPtr lwndC; // Holds the unmanaged handle of the control<BR>private IntPtr mControlPtr; // Holds the managed pointer of the control<BR>private int mWidth;<BR>private int mHeight;<BR>&nbsp;<BR>private showVideo.FrameEventHandler mFrameEventHandler; // Delegate instance for the frame callback - must keep alive! gc should NOT collect it<BR>&nbsp;<BR>// Close the web camera<BR>public void CloseWebcam()<BR>{<BR>this.capDriverDisconnect(this.lwndC);<BR>}<BR>&nbsp;<BR>// start the web camera<BR>public void StartWebCam()<BR>{<BR>byte[] lpszName = new byte[100];<BR>byte[] lpszVer = new byte[100];<BR>&nbsp;<BR>showVideo.capGetDriverDescriptionA(0, lpszName, 100,lpszVer, 100);<BR>this.lwndC = showVideo.capCreateCaptureWindowA(lpszName, showVideo.WS_VISIBLE + showVideo.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0);<BR>&nbsp;<BR>if (this.capDriverConnect(this.lwndC, 0))<BR>{<BR>this.capPreviewRate(this.lwndC, 66);<BR>this.capPreview(this.lwndC, true);<BR>showVideo.BITMAPINFO bitmapinfo = new showVideo.BITMAPINFO(); <BR>bitmapinfo.bmiHeader.biSize = showVideo.SizeOf(bitmapinfo.bmiHeader);<BR>bitmapinfo.bmiHeader.biWidth = 352;<BR>bitmapinfo.bmiHeader.biHeight = 288;<BR>bitmapinfo.bmiHeader.biPlanes = 1;<BR>bitmapinfo.bmiHeader.biBitCount = 24;<BR>this.capSetVideoFormat(this.lwndC, ref bitmapinfo, showVideo.SizeOf(bitmapinfo));<BR>this.mFrameEventHandler = new showVideo.FrameEventHandler(FrameCallBack);<BR>this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler);<BR>showVideo.SetWindowPos(this.lwndC, 0, 0, 0, mWidth , mHeight , 6);<BR>} <BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>// private functions<BR>private bool capDriverConnect(IntPtr lwnd, short i)<BR>{<BR>return showVideo.SendMessage(lwnd, showVideo.WM_CAP_DRIVER_CONNECT, i, 0);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>private bool capDriverDisconnect(IntPtr lwnd)<BR>{<BR>return showVideo.SendMessage(lwnd, showVideo.WM_CAP_DRIVER_DISCONNECT, 0, 0);<BR>}<BR>&nbsp;<BR>private bool capPreview(IntPtr lwnd, bool f)<BR>{<BR>return showVideo.SendMessage(lwnd, showVideo.WM_CAP_SET_PREVIEW , f, 0);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>private bool capPreviewRate(IntPtr lwnd, short wMS)<BR>{<BR>return showVideo.SendMessage(lwnd, showVideo.WM_CAP_SET_PREVIEWRATE, wMS, 0);<BR>}<BR>&nbsp;<BR>private bool capSetCallbackOnFrame(IntPtr lwnd, showVideo.FrameEventHandler lpProc)<BR>{ <BR>return showVideo.SendMessage(lwnd, showVideo.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>private bool capSetVideoFormat(IntPtr hCapWnd, ref showVideo.BITMAPINFO BmpFormat, int CapFormatSize)<BR>{<BR>return showVideo.SendMessage(hCapWnd, showVideo.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);<BR>}</DIV>
<DIV>&nbsp;</DIV>
<DIV>private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)<BR>{<BR>showVideo.VIDEOHDR videoHeader = new showVideo.VIDEOHDR();<BR>byte[] VideoData;<BR>videoHeader = (showVideo.VIDEOHDR)showVideo.GetStructure(lpVHdr,videoHeader);<BR>VideoData = new byte[videoHeader.dwBytesUsed];<BR>showVideo.Copy(videoHeader.lpData ,VideoData);<BR>if (this.RecievedFrame != null)<BR>this.RecievedFrame (VideoData);<BR>}<BR>}<BR>}<BR>具体调用如下：<BR>using System;<BR>using System.Drawing;<BR>using System.Collections;<BR>using System.ComponentModel;<BR>using System.Windows.Forms;<BR>using System.Data;<BR>using webcam;<BR>namespace webcam<BR>{<BR>/// <BR>/// Form1 的摘要说明。<BR>/// <BR>public class Form1 : System.Windows.Forms.Form<BR>{<BR>private System.Windows.Forms.Panel panelPreview;<BR>private System.Windows.Forms.Button b_play;<BR>private System.Windows.Forms.Button b_stop;<BR>/// <BR>/// 必需的设计器变量。<BR>/// <BR>private System.ComponentModel.Container components = null;<BR>WebCamera wc;<BR>public Form1()<BR>{<BR>//<BR>// Windows 窗体设计器支持所必需的<BR>//<BR>InitializeComponent();<BR>//<BR>// TODO: 在 InitializeComponent 调用后添加任何构造函数代码<BR>//<BR>}<BR>/// <BR>/// 清理所有正在使用的资源。<BR>/// <BR>protected override void Dispose( bool disposing )<BR>{<BR>if( disposing )<BR>{<BR>if (components != null) <BR>{<BR>components.Dispose();<BR>}<BR>}<BR>base.Dispose( disposing );<BR>}<BR>#region Windows 窗体设计器生成的代码<BR>/// <BR>/// 设计器支持所需的方法 - 不要使用代码编辑器修改<BR>/// 此方法的内容。<BR>/// <BR>private void InitializeComponent()<BR>{<BR>this.b_play = new System.Windows.Forms.Button();<BR>this.panelPreview = new System.Windows.Forms.Panel();<BR>this.b_stop = new System.Windows.Forms.Button();<BR>this.SuspendLayout();<BR>// <BR>// b_play<BR>// <BR>this.b_play.Location = new System.Drawing.Point(280, 368);<BR>this.b_play.Name = "b_play";<BR>this.b_play.TabIndex = 0;<BR>this.b_play.Text = "&amp;Play";<BR>this.b_play.Click += new System.EventHandler(this.button1_Click);<BR>// <BR>// panelPreview<BR>// <BR>this.panelPreview.Location = new System.Drawing.Point(8, 8);<BR>this.panelPreview.Name = "panelPreview";<BR>this.panelPreview.Size = new System.Drawing.Size(344, 272);<BR>this.panelPreview.TabIndex = 1;<BR>// <BR>// b_stop<BR>// <BR>this.b_stop.Enabled = false;<BR>this.b_stop.Location = new System.Drawing.Point(360, 368);<BR>this.b_stop.Name = "b_stop";<BR>this.b_stop.TabIndex = 2;<BR>this.b_stop.Text = "&amp;Stop";<BR>this.b_stop.Click += new System.EventHandler(this.b_stop_Click);<BR>// <BR>// Form1<BR>// <BR>this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);<BR>this.ClientSize = new System.Drawing.Size(464, 413);<BR>this.Controls.Add(this.b_stop);<BR>this.Controls.Add(this.panelPreview);<BR>this.Controls.Add(this.b_play);<BR>this.MaximizeBox = false;<BR>this.MinimizeBox = false;<BR>this.Name = "Form1";<BR>this.Text = "GoodView test Web Camera";<BR>this.Load += new System.EventHandler(this.Form1_Load);<BR>this.ResumeLayout(false);<BR>}<BR>#endregion<BR>/// <BR>/// 应用程序的主入口点。<BR>/// <BR>[STAThread]<BR>static void Main() <BR>{<BR>Application.Run(new Form1());<BR>}<BR>private void Form1_Load(object sender, System.EventArgs e)<BR>{<BR>b_play.Enabled = false;<BR>b_stop.Enabled = true;<BR>panelPreview.Size = new Size(330,330);<BR>wc = new WebCamera( panelPreview.Handle,panelPreview.Width,panelPreview.Height);<BR>wc.StartWebCam();<BR>}<BR>private void button1_Click(object sender, System.EventArgs e)<BR>{<BR>b_play.Enabled = false;<BR>b_stop.Enabled = true;<BR>panelPreview.Size = new Size(330,330);<BR>wc = new WebCamera( panelPreview.Handle,panelPreview.Width,panelPreview.Height);<BR>wc.StartWebCam();<BR>}<BR>private void b_stop_Click(object sender, System.EventArgs e)<BR>{<BR>b_play.Enabled = true;<BR>b_stop.Enabled = false;<BR>wc.CloseWebcam();<BR>}<BR>}<BR>}<BR></DIV>]]></description>
</item>
</channel>
</rss>