﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-五味子</title><link>http://www.cnblogs.com/mysoft/</link><description>温；酸、甘；归肺、心、肾经“酸咸入肝而补肾，辛苦入心而补肺，甘入中宫益脾胃“——《本草纲目》</description><language>zh-cn</language><lastBuildDate>Sun, 21 Mar 2010 19:46:57 GMT</lastBuildDate><pubDate>Sun, 21 Mar 2010 19:46:57 GMT</pubDate><ttl>60</ttl><item><title>佛说，人为什么会有烦恼</title><link>http://www.cnblogs.com/mysoft/archive/2009/07/15/1523970.html</link><dc:creator>五味子</dc:creator><author>五味子</author><pubDate>Wed, 15 Jul 2009 03:36:00 GMT</pubDate><guid>http://www.cnblogs.com/mysoft/archive/2009/07/15/1523970.html</guid><description><![CDATA[<p>阅读: 145 评论: 1 作者: <a href="http://www.cnblogs.com/mysoft/" target="_blank">五味子</a> 发表于 2009-07-15 11:36 <a href="http://www.cnblogs.com/mysoft/archive/2009/07/15/1523970.html" target="_blank">原文链接</a></p>&nbsp;&nbsp;&nbsp; 人最大的邪见就是以为一切美好珍贵的东西，都得经过艰苦努力向外追求才会得到。事实上，世间最珍贵的东西都是不求自得的。空气、阳光、水，哪一样不比金银财宝、总统位置重要？没有后者，人还能生存，但没有了空气、阳光和水，人根本就不能生存。&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;就人本身来说，最珍贵的东西上天早就免费送给你了。眼、耳、鼻舌、手、脚都是最珍贵的。如果有人说愿用总统的位子及无数的珍宝来换取你的双眼或你的双手，你愿意换吗，一定不愿意的。可见眼耳鼻舌手脚要比权位、财富还要贵重。&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;当然还有比眼耳鼻舌身意更珍贵的，那就是让你能看、能听、能动、能思维的灵妙无比的心。可惜人们注重的往往都是外在事物，从来不去关照最最重要的心。&nbsp;<br /><br />&nbsp;&nbsp;  要想让无形的心获得快乐，只有用无形的修持，那就是不住一切相，没有分别心。&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;实 际上，生命的本质就是乐，根本就无需追求。人人都活在无量光明的极乐世界中，为何我们却觉察不到？就是因为有分别心。有了分别心，就有了爱憎之念，认为这 个我喜欢，那个我不喜欢，接着就想得到自己所喜欢的，舍去自己所不喜欢的。然而往往却是取不到、舍不掉。自己所喜欢的总是离你远去，而所讨厌的又偏偏与你 绑在一起，于是就产生种种烦恼和痛苦。所以说烦恼、痛苦都是人自己创造出来的。&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;人最大苦恼就是不愿接受现实，不能认识实相。强取分别，强要取舍，恩恩怨怨就从这儿产生。&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;事实上，这个世界根本就没有孤立的东西可以取舍。世界本是一合相，有取有舍都是妄想。就如同眼耳鼻舌手脚及五脏六腑组成了你这个人体，你能对哪个器官进行取 舍呢？明明不可取不可舍，却要强取强舍，这就是愚昧。费尽心机去取、去舍，最终还是取不到，舍不掉，自找烦恼。 <img src="http://www.cnblogs.com/mysoft/aggbug/1523970.html?type=1" width="1" height="1" alt=""/><p>评论: 1　<a href="http://www.cnblogs.com/mysoft/archive/2009/07/15/1523970.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/mysoft/archive/2009/07/15/1523970.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59300/" target="_blank">谷歌“身后事”：屏蔽.com不只是个传说？</a><span style="color:gray">(2010-03-21 22:47)</span><br/>· <a href="http://news.cnblogs.com/n/59299/" target="_blank">腾讯今年招聘近3000人 员工总数将突破1万人</a><span style="color:gray">(2010-03-21 22:39)</span><br/>· <a href="http://news.cnblogs.com/n/59298/" target="_blank">中国互联网江湖一窥：IT第一记者刘韧入狱记</a><span style="color:gray">(2010-03-21 22:17)</span><br/>· <a href="http://news.cnblogs.com/n/59295/" target="_blank">9大IT科技公司总部览</a><span style="color:gray">(2010-03-21 21:00)</span><br/>· <a href="http://news.cnblogs.com/n/59293/" target="_blank">五个广泛流传的对大龄程序员的误解</a><span style="color:gray">(2010-03-21 19:51)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59293/" target="_blank">五个广泛流传的对大龄程序员的误解</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>对比.NET PetShop和Duwamish来探讨Ado.NET的数据库编程模式(转载)</title><link>http://www.cnblogs.com/mysoft/archive/2005/06/08/170550.html</link><dc:creator>五味子</dc:creator><author>五味子</author><pubDate>Wed, 08 Jun 2005 10:54:00 GMT</pubDate><guid>http://www.cnblogs.com/mysoft/archive/2005/06/08/170550.html</guid><description><![CDATA[<p>阅读: 543 评论: 2 作者: <a href="http://www.cnblogs.com/mysoft/" target="_blank">五味子</a> 发表于 2005-06-08 18:54 <a href="http://www.cnblogs.com/mysoft/archive/2005/06/08/170550.html" target="_blank">原文链接</a></p><div align=left><a name=#top>专栏作品</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 卢彦 </div>
<div align=center>
<hr align=center width="100%" color=#cccccc noShade SIZE=1>
</div>
<div align=left>.NET PetShop和Duwamish简单介绍</div>
<div align=left>相信大家一定听说过有名的"宠物店大战"，没错，本文的主角之一就是获胜方.NET PetShop，微软号称以27倍的速度和1/4的代码量遥遥领先于基于J2EE的PetStore宠物商店。虽然SUN也曾对此抱怨过不满，指责此"大战"有水分，不过无论如何，.NET PetShop绝对是一个经典的.NET实例教程，至少为我们提供了一条赶超J2EE的&#8220;捷径&#8221; ：）,它的下载地址是：<a href="http://www.gotdotnet.com/team/compare">http://www.gotdotnet.com/team/compare</a></div>
<div align=left></div>
<div align=left><b>.NET PetShop</b><b>宠物网上商店首页</b></div>
<div align=left>而Duwamish则是一个外表简单，内部却极其复杂的一个网上书店的.NET完整应用范例，作为一个微软官方的Sample，它同时提供了C#和VB.NET两种语言版本，并且还附上了大量详尽的中文资料，如果打印出来，实在是居家旅行，临睡入厕必备之物。什么？您没听说过？呵呵，如果您装了Visual Studio .NET的话，它就在您的硬盘上静静的躺着呢，不过还没有被安装，您可以在您的VS.NET 的Enterprise Samples目录下找到并安装它，例如：C:\Program Files\Microsoft Visual Studio .NET\Enterprise Samples\Duwamish 7.0 CS。</div>
<div align=left></div>
<div align=left><b>Duwamish</b><b>网上电子书店首页</b></div>
<div align=left>结构简述</div>
<div align=left>两家商店都采用了n层应用结构（毫无疑问，n层结构的应用架构应该绝对是您开发.NET应用的首选，哪怕您只想做一个网页计数器），不同的是，PetShop采用的是最常见的三层应用结构，分别为表示层，中间层和数据层。而Duwamish则采用的是一个四层应用结构，并使用不同的项目分隔开，分别为表示层，业务外观层，业务规则层和数据层。至于这两种结构分别有什么优点和缺点，以及为什么要这么分层，我们不进行详细讨论，因为本文的重点不在于此。我们主要分析的是他们的数据库编程的模式。</div>
<div align=left>Duwamish数据访问剖析</div>
<div align=left>首先，我们来看看Duwamish书店，它采用的是DataAdapter和DataSet配合的数据存储模式，所不同的是，它对DataSet进行子类化扩展作为数据载体，也就是采用定制的DataSet来进行层间的数据传输，下面是一个定制的DataSet示例：</div>
<div align=left>public class BookData : DataSet</div>
<div align=left>{</div>
<div align=left>&nbsp; public BookData()</div>
<div align=left>&nbsp; {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create the tables in the dataset</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BuildDataTables();</div>
<div align=left>&nbsp; }</div>
<div align=left>&nbsp; private void BuildDataTables()</div>
<div align=left>&nbsp; {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create the Books table</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataTable table&nbsp;&nbsp; = new DataTable(BOOKS_TABLE);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataColumnCollection columns = table.Columns;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(PKID_FIELD, typeof(System.Int32));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(TYPE_ID_FIELD, typeof(System.Int32));</div>
<div align=left>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;columns.Add(PUBLISHER_ID_FIELD, typeof(System.Int32));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(PUBLICATION_YEAR_FIELD, typeof(System.Int16));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(ISBN_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(IMAGE_FILE_SPEC_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;columns.Add(TITLE_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(DESCRIPTION_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(UNIT_PRICE_FIELD, typeof(System.Decimal));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(UNIT_COST_FIELD, typeof(System.Decimal));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(ITEM_TYPE_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; columns.Add(PUBLISHER_NAME_FIELD, typeof(System.String));</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Tables.Add(table);</div>
<div align=left>&nbsp; }</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;</div>
<div align=left>}</div>
<div align=left>&nbsp;</div>
<div align=left>我们可以看到它有一个BuildDataTables方法，并且在构造函数中调用，这样，定制的Books表就和这个DataSet捆绑在一起了，省得以后还要进行Column Mapping，这真是个好主意，我怎么就没有想到呢？ ：）</div>
<div align=left>解决了数据结构，接下来看看数据层的代码实现，在Duwamish中，数据层中有5个类，分别是Books，Categories，Customers和Orders，每个类分别只负责有关数据的存取。下面是其中一个类的示例代码：</div>
<div align=left>private SqlDataAdapter dsCommand;</div>
<div align=left>public BookData GetBookById(int bookId)</div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp; return FillBookData("GetBookById", "@BookId", bookId.ToString());</div>
<div align=left>}</div>
<div align=left>private BookData FillBookData(String commandText, String paramName, String paramValue)</div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp; if (dsCommand == null )</div>
<div align=left>&nbsp;&nbsp;&nbsp; {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new System.ObjectDisposedException( GetType().FullName );</div>
<div align=left>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp; BookData&nbsp;&nbsp; data&nbsp;&nbsp;&nbsp; = new BookData();</div>
<div align=left>&nbsp;&nbsp;&nbsp; SqlCommand command = dsCommand.SelectCommand;</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp; command.CommandText = commandText;</div>
<div align=left>&nbsp;&nbsp;&nbsp; command.CommandType = CommandType.StoredProcedure; // use stored proc for perf</div>
<div align=left>&nbsp;&nbsp;&nbsp; SqlParameter param = new SqlParameter(paramName, SqlDbType.NVarChar, 255);</div>
<div align=left>&nbsp;&nbsp;&nbsp; param.Value = paramValue;</div>
<div align=left>&nbsp;&nbsp;&nbsp; command.Parameters.Add(param);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp; dsCommand.Fill(data);</div>
<div align=left>&nbsp;&nbsp;&nbsp; return data;</div>
<div align=left>}</div>
<div align=left>&nbsp;</div>
<div align=left>这里就是数据层的代码了，我们在这里可以看到Duwamish采用了DataAdapter来将数据填充到定制的DataSet中，然后返回该DataSet。我感到很奇怪的是在数据存取层中竟然可以看到GetBookById这样具体的数据存取方法，虽然最后还是有一个抽象出来的FillBookData方法，但是上面还有三层啊，底层都做到这份上了，那上层都做些什么呢？答案是数据检查，上层基本上都在做一些很严密的数据合法性校验（当然也会包括一些比较复杂的事务逻辑，但是并不多），示例代码如下：</div>
<div align=left>public CustomerData GetCustomerByEmail(String emailAddress, String password)</div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp; // Check preconditions</div>
<div align=left>&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp; ApplicationAssert.CheckCondition(emailAddress != String.Empty, "Email address is required",</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationAssert.LineNumber);</div>
<div align=left>&nbsp;&nbsp;&nbsp; ApplicationAssert.CheckCondition(password != String.Empty, "Password is required", </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationAssert.LineNumber);</div>
<div align=left>&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp; // Get the customer dataSet</div>
<div align=left>&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp; CustomerData dataSet;</div>
<div align=left>&nbsp;&nbsp;&nbsp; using (DataAccess.Customers customersDataAccess = new DataAccess.Customers())</div>
<div align=left>&nbsp;&nbsp;&nbsp; {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);</div>
<div align=left>&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp; // Verify the customer's password</div>
<div align=left>&nbsp;&nbsp;&nbsp; //</div>
<div align=left>&nbsp;&nbsp;&nbsp; DataRowCollection rows = dataSet.Tables[CustomerData.CUSTOMERS_TABLE].Rows;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp; if ( ( rows.Count == 1 ) &amp;&amp; rows[0][CustomerData.PASSWORD_FIELD].Equals(password) )</div>
<div align=left>&nbsp;&nbsp;&nbsp; {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return dataSet;</div>
<div align=left>&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;&nbsp;&nbsp; else</div>
<div align=left>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;</div>
<div align=left>&nbsp;&nbsp;&nbsp; }</div>
<div align=left>}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;</div>
<div align=left>在这个方法中，真正进行数据存取的实际上只有</div>
<div align=left>dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);</div>
<div align=left>这么一句，是直接调用的数据层。其它都是在进行合法性校验，我们可以感悟到，进行一个真正的企业级开发需要考虑的系统健壮性有多么重要。</div>
<div align=left>.NET PetShop数据访问剖析</div>
<div align=left>OK，Duwamish看完了，下面我们来看看PetShop的数据访问机制。</div>
<div align=left>PetShop只有一个项目，它采用的分层办法是将中间层和数据层都写成cs文件放在Components目录里，其中数据层就是一个名为Database的类，它封装了所有对数据库的底层操作。下面是示例代码段：</div>
<div align=left>public void RunProc(string procName, out SqlDataReader dataReader) </div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlCommand cmd = CreateCommand(procName, null);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataReader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);</div>
<div align=left>}</div>
<div align=left>&nbsp;</div>
<div align=left>我们看到了一个跟Duwamish截然不同的另一种数据访问方式，它将所有的数据访问方法抽象出来做成一个RunProc方法，至于返回数据呢，呵呵，它有点偷懒，直接返回一个DataReader给你，你自己去读吧。还记得Duwamish采用的层间数据传输载体是什么吗？对了，是DataSet，它被数据层填充后返回给了中间层。但是这里，数据层和传输层的数据传输载体变成了DataReader，实际上，还不能称它为数据载体，因为数据还没开始读呢，在这里，DataReader的作用和指针有点类似，也许我们应该称它为&#8220;数据引用&#8221;：）</div>
<div align=left>接着往下看，DataReader被怎么&#8220;处理&#8221;的：</div>
<div align=left>public ProductResults[] GetList(string catid, int currentPage, int pageSize, ref int numResults) </div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numResults = 0;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int index=0;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlDataReader reader = GetList(catid);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProductResults[] results = new ProductResults[pageSize];</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // now loop through the list and pull out items of the specified page</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int start = (int)((currentPage - 1) * pageSize);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (start &lt;= 0) start = 1;</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // skip </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; start - 1; i++) {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (reader.Read()) numResults++;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (start &gt; 1) reader.Read();</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // read the data we are interested in</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (reader.Read()) {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (index &lt; pageSize) {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; results[index] = new ProductResults();</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; results[index].productid = reader.GetString(0);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; results[index].name =&nbsp; reader.GetString(1);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; index++;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numResults++;&nbsp;&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reader.Close();</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // see if need to redim array</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (index == pageSize)</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return results;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // not a full page, redim array</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ProductResults[] results2 = new ProductResults[index];</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Array.Copy(results, results2, index);</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return results2;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </div>
<div align=left>}</div>
<div align=left>注意到currentPage和pageSize了吗？原来在这里就进行了数据分页，只返回满足需要的最少的数据量，而不是象我们很多喜欢偷懒的人一样，简单的将整个DataTable一股脑的绑定到DataGrid，造成大量的数据冗余。</div>
<div align=left>在这里，数据被真正的读出来，并且被手动填充到一个自定义的对象数组中，我们来看看这个数组的定义：</div>
<div align=left>public class ProductResults </div>
<div align=left>{</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string m_productid;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string m_name;</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // product props</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string productid {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return m_productid; }</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { m_productid = value; }&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div align=left>&nbsp;</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string name {</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return m_name; }</div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { m_name = value; }&nbsp; </div>
<div align=left>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div align=left>}</div>
<div align=left>非常之简单，不过我有点奇怪为什么不使用struct呢？是不是.NET中struct和class的性能差距已经可以忽略不计了？</div>
<div align=left>分析总结</div>
<div align=left>通过观察这两个商店的具体实现，我们得到了两个不同的数据访问模式，Duwamish采用的是以DataSet为核心，因为DataSet提供了这方面大量的相关方法，所以整个应用的数据传输，数据格式定义，数据校验都围绕着DataSet来进行，整个架构定义非常清晰和严谨，但是却显得有些庞大。PetShop在整个程序中没有采用一个DataSet，程序非常的简洁，轻灵，但是没有Duwamish那么强的健壮性。这两个程序是Microsoft公司不同的小组写出来的代码，所以有着不同风格。不过都应该能代表.NET的标准模式。看到这里，你应该对文章开头提出的那些疑问有一个比较形象的认识了吧。</div>
<div align=left>另外，请再次注意，PetShop在打开数据连接之后，并没有马上读取数据，而是将DataReader传递给另外的对象来执行数据读的操作，然后才关闭连接。这样，数据连接的时间加长了，而数据库连接是一项非常宝贵的服务器资源，相比之下，Dawamish在连接数据库之后马上进行填充，然后迅速释放掉数据库连接的方式更加有利于大量用户的并发访问。</div>
<div align=left>再一点，上文的程序中没有提到更新操作，PetShop采用的是使用Command对象执行单个存储过程的方式来进行更新操作，是属于一种在线即时数据更新模式。而Dawamish采用的是DataAdapter的Update方法，将DataSet的改变一次性的提交到数据库中，属于离线数据更新模式。这种模式的好处是可以一次性更新大批量数据，减少数据库的连接次数。缺点是如果数据库在改动非常频繁的情况下需要实时的跟踪数据变化就不合适了。需要根据具体的情况采用具体的数据更新办法。</div>
<div align=left>总的来说，如果您只需要快速的读取数据并显示出来，推荐您采用DataReader，如果您需要对数据进行大量的修改，还有大量并发访问的可能，而且不需要实时的跟踪数据库的变化，推荐您使用DataSet。当然，这两种情况有点极端了，实际的应用环境也许有着很复杂的条件，具体需要您自己审时度势，综合采用，不过我个人还是比较喜欢PetShop那种轻灵的风格 ：）</div>
<div align=left>本文只尝试对以上两个典型的.NET应用例程的数据访问机制做了一个简单的追踪分析，如果有希望能对此例进行其它方面的研究或者就本话题继续进行更加深入探讨的朋友，请发Email到我的信箱：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#110;&#108;&#117;&#121;&#97;&#110;&#64;&#49;&#54;&#51;&#46;&#78;&#69;&#84;">nluyan@163.NET</a>，谢谢。</div>
<img src="http://www.cnblogs.com/mysoft/aggbug/170550.html?type=1" width="1" height="1" alt=""/><p>评论: 2　<a href="http://www.cnblogs.com/mysoft/archive/2005/06/08/170550.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/mysoft/archive/2005/06/08/170550.html#commentform" target="_blank">发表评论</a></p><p><a href="http://job.cnblogs.com/" target="_blank">找优秀程序员，就在博客园</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/59300/" target="_blank">谷歌“身后事”：屏蔽.com不只是个传说？</a><span style="color:gray">(2010-03-21 22:47)</span><br/>· <a href="http://news.cnblogs.com/n/59299/" target="_blank">腾讯今年招聘近3000人 员工总数将突破1万人</a><span style="color:gray">(2010-03-21 22:39)</span><br/>· <a href="http://news.cnblogs.com/n/59298/" target="_blank">中国互联网江湖一窥：IT第一记者刘韧入狱记</a><span style="color:gray">(2010-03-21 22:17)</span><br/>· <a href="http://news.cnblogs.com/n/59295/" target="_blank">9大IT科技公司总部览</a><span style="color:gray">(2010-03-21 21:00)</span><br/>· <a href="http://news.cnblogs.com/n/59293/" target="_blank">五个广泛流传的对大龄程序员的误解</a><span style="color:gray">(2010-03-21 19:51)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/59293/" target="_blank">五个广泛流传的对大龄程序员的误解</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>