﻿<?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>IT博客-Welcome To Oliver_Yin's  Blog!-文章分类-NET Programming</title><link>http://www.cnitblog.com/oliver_yin/category/489.html</link><description>打字--&gt; 死打字--&gt;抄写程序--&gt;研究程序--&gt;分析需求 
--&gt;分析架构--&gt;项目管理--&gt;企业信息化--&gt;.........</description><language>zh-cn</language><lastBuildDate>Wed, 28 Sep 2011 02:05:02 GMT</lastBuildDate><pubDate>Wed, 28 Sep 2011 02:05:02 GMT</pubDate><ttl>60</ttl><item><title>在窗体上使用Windows XP风格的控件(转载)</title><link>http://www.cnitblog.com/oliver_yin/articles/6444.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Sun, 05 Feb 2006 13:21:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/6444.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/6444.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/6444.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/6444.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/6444.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一．概要Windows XP开创了一种全新的Windows用户界面（UI），这种用户界面给用户一种现代化的、超时髦的感受。Windows XP新创了闪亮的具有圆形边角的控件以及极富未来派气息的进度条等具有新风格的控件。而现在的Visual Studio.Net也具备了此类控件。那么开发者就想能否在自己开发的程序中使用这类超酷的控件呢。答案是肯定的，程序员所要做的仅仅...&nbsp;&nbsp;<a href='http://www.cnitblog.com/oliver_yin/articles/6444.html'>阅读全文</a><img src ="http://www.cnitblog.com/oliver_yin/aggbug/6444.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2006-02-05 21:21 <a href="http://www.cnitblog.com/oliver_yin/articles/6444.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>漫谈.Net PetShop和Duwamish ADO.NET数据库编程</title><link>http://www.cnitblog.com/oliver_yin/articles/5513.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Sat, 17 Dec 2005 09:17:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/5513.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/5513.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/5513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/5513.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/5513.html</trackback:ping><description><![CDATA[<TABLE class=partsmb cellSpacing=0 border=0>
<TBODY>
<TR>
<TD></TD>
<TD class=bvBody>
<DIV id=entrycns!1pRd_P5HlUt8TMD3Q2NITYMA!173>
<TABLE class="fixedTable blogpost" cellSpacing=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=bvh8></TD></TR>
<TR>
<TD vAlign=top><SPAN class=bold id=LastMDatecns!1pRd_P5HlUt8TMD3Q2NITYMA!173><STRONG>6月27日</STRONG></SPAN></TD></TR>
<TR>
<TD height=4><STRONG></STRONG></TD></TR>
<TR>
<TD class=blackline><STRONG></STRONG></TD></TR>
<TR>
<TD height=4><STRONG></STRONG></TD></TR>
<TR>
<TD class=ellipse><SPAN class=bvTitle id=subjcns!1pRd_P5HlUt8TMD3Q2NITYMA!173><STRONG>漫谈.Net PetShop和Duwamish ADO.NET数据库编程-1</STRONG></SPAN></TD></TR>
<TR>
<TD class=bvh8><STRONG></STRONG></TD></TR>
<TR>
<TD id=msgcns!1pRd_P5HlUt8TMD3Q2NITYMA!173>
<P><STRONG>概述<BR><BR></STRONG>　　ADO.Net为我们提供了强大的数据库开发能力，它内置的多个对象为我们的数据库编程提供了不同的选择。但是在允许我们灵活选用的同时，许多初学者也很迷惑，我到底是应该使用DataReader还是应该使用DataAdapter？我只想读取一小部分数据，难道我一定要Fill满整个DataSet吗？为什么DataReader不能和RecordSet一样提供一个数据更新的方法？DataSet到底有什么好处？<BR><BR>　　在本文中，我将对.Net PetShop的数据库编程模式和Duwamish的数据库编程模式进行一些简单的分析和对比。如果您也有以上疑问的话，相信在读完本文之后，就可以根据具体的需要来制定一个最适合您应用的数据库编程模式。<BR><BR>　　<B>.Net PetShop和Duwamish简单介绍</B><BR><BR>　　相信大家一定听说过有名的"宠物店大战"，没错，本文的主角之一就是获胜方.Net PetShop，微软号称以27倍的速度和1/4的代码量遥遥领先于基于J2EE的PetStore宠物商店。虽然SUN也曾对此抱怨过不满，指责此"大战"有水分，不过无论如何，.Net PetShop绝对是一个经典的.Net实例教程，至少为我们提供了一条赶超J2EE的“捷径=" ：）,它的下载地址是：<A href="http://www.gotdotnet.com/team/compare " target=_blank><FONT color=#000000>http://www.gotdotnet.com/team/compare </FONT></A><BR></P>
<P align=center><BR><IMG height=16 src="http://www.webabc.com.cn/servers/bbs/skins/default/filetype/gif.gif" width=16 border=0>此主题相关图片如下：<BR><A id=ImgSpan href="http://www.webabc.com.cn/servers/bbs/UploadFile/2005-6/2005639241295131.gif" target=_blank><IMG height=251 alt=按此在新窗口浏览图片 src="http://www.webabc.com.cn/servers/bbs/UploadFile/2005-6/2005639241295131.gif" width=300 border=0></A></P>
<P align=center>.Net PetShop宠物网上商店首页</P>
<P>　　 而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。</P>
<P align=center><BR><BR>Duwamish网上电子书店首页</P>
<P>　　<B>结构简述</B><BR><BR>　　两家商店都采用了n层应用结构（毫无疑问，n层结构的应用架构应该绝对是您开发.Net应用的首选，哪怕您只想做一个网页计数器），不同的是，PetShop采用的是最常见的三层应用结构，分别为表示层，中间层和数据层。而Duwamish则采用的是一个四层应用结构，并使用不同的项目分隔开，分别为表示层，业务外观层，业务规则层和数据层。至于这两种结构分别有什么优点和缺点，以及为什么要这么分层，我们不进行详细讨论，因为本文的重点不在于此。我们主要分析的是他们的数据库编程的模式。<BR><STRONG>Duwamish数据访问剖析<BR><BR></STRONG>　　首先，我们来看看Duwamish书店，它采用的是DataAdapter和DataSet配合的数据存储模式，所不同的是，它对DataSet进行子类化扩展作为数据载体，也就是采用定制的DataSet来进行层间的数据传输，下面是一个定制的DataSet示例：<BR><BR>public class BookData : DataSet<BR>&nbsp;&nbsp;&nbsp;&nbsp; {<BR>public BookData()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create the tables in the dataset<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BuildDataTables();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void BuildDataTables()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Create the Books table<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataTable table&nbsp;&nbsp; = new DataTable(BOOKS_TABLE);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataColumnCollection columns = table.Columns;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp; columns.Add(PKID_FIELD, typeof(System.Int32));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(TYPE_ID_FIELD, typeof(System.Int32));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(PUBLISHER_ID_FIELD, typeof(System.Int32));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(PUBLICATION_YEAR_FIELD, typeof(System.Int16));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(ISBN_FIELD, typeof(System.String));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(IMAGE_FILE_SPEC_FIELD, typeof(System.String));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(TITLE_FIELD, typeof(System.String));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(DESCRIPTION_FIELD, typeof(System.String));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(UNIT_PRICE_FIELD, typeof(System.Decimal));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(UNIT_COST_FIELD, typeof(System.Decimal));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(ITEM_TYPE_FIELD, typeof(System.String));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns.Add(PUBLISHER_NAME_FIELD, typeof(System.String));<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;this.Tables.Add(table);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>………<BR>}</P>
<P>　　我们可以看到它有一个BuildDataTables方法，并且在构造函数中调用，这样，定制的Books表就和这个DataSet捆绑在一起了，省得以后还要进行Column Mapping，这真是个好主意，我怎么就没有想到呢？ ：）<BR><BR>　　解决了数据结构，接下来看看数据层的代码实现，在Duwamish中，数据层中有5个类，分别是Books，Categories，Customers和Orders，每个类分别只负责有关数据的存取。下面是其中一个类的示例代码：<BR></P>
<P>private SqlDataAdapter dsCommand;<BR>public BookData GetBookById(int bookId)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp; return FillBookData("GetBookById", "@BookId", bookId.ToString());<BR>}<BR>private BookData FillBookData(String commandText, String paramName, String paramValue)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (dsCommand == null )<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new System.ObjectDisposedException( GetType().FullName );<BR>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;BookData&nbsp;&nbsp; data&nbsp;&nbsp;&nbsp;&nbsp;= new BookData();<BR>&nbsp;&nbsp;&nbsp;&nbsp;SqlCommand command = dsCommand.SelectCommand;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;command.CommandText = commandText;<BR>&nbsp;&nbsp;&nbsp;&nbsp;command.CommandType = CommandType.StoredProcedure; // use stored proc for perf<BR>&nbsp;&nbsp;&nbsp;&nbsp;SqlParameter param = new SqlParameter(paramName, SqlDbType.NVarChar, 255);<BR>&nbsp;&nbsp;&nbsp;&nbsp;param.Value = paramValue;<BR>&nbsp;&nbsp;&nbsp;&nbsp;command.Parameters.Add(param);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;dsCommand.Fill(data);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return data;<BR>}</P>
<P>　　这里就是数据层的代码了，我们在这里可以看到Duwamish采用了DataAdapter来将数据填充到定制的DataSet中，然后返回该DataSet。我感到很奇怪的是在数据存取层中竟然可以看到GetBookById这样具体的数据存取方法，虽然最后还是有一个抽象出来的FillBookData方法，但是上面还有三层啊，底层都做到这份上了，那上层都做些什么呢？答案是数据检查，上层基本上都在做一些很严密的数据合法性校验（当然也会包括一些比较复杂的事务逻辑，但是并不多），示例代码如下：<BR></P>
<P>public CustomerData GetCustomerByEmail(String emailAddress, String password)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Check preconditions<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ApplicationAssert.CheckCondition(emailAddress != String.Empty, "Email address is required",<BR>ApplicationAssert.LineNumber);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ApplicationAssert.CheckCondition(password != String.Empty, "Password is required", <BR>ApplicationAssert.LineNumber);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Get the customer dataSet<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomerData dataSet;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using (DataAccess.Customers customersDataAccess = new DataAccess.Customers())<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Verify the customer's password<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataRowCollection rows = dataSet.Tables[CustomerData.CUSTOMERS_TABLE].Rows;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( ( rows.Count == 1 ) &amp;&amp; rows[0][CustomerData.PASSWORD_FIELD].Equals(password) )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return dataSet;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} </P>
<P>　　在这个方法中，真正进行数据存取的实际上只有<BR><BR>　　dataSet = customersDataAccess.LoadCustomerByEmail(emailAddress);<BR><BR>　　这么一句，是直接调用的数据层。其它都是在进行合法性校验，我们可以感悟到，进行一个真正的企业级开发需要考虑的系统健壮性有多么重要。<BR><STRONG>.Net PetShop数据访问剖析<BR><BR></STRONG>　　OK，Duwamish看完了，下面我们来看看PetShop的数据访问机制。<BR><BR>　　PetShop只有一个项目，它采用的分层办法是将中间层和数据层都写成cs文件放在Components目录里，其中数据层就是一个名为Database的类，它封装了所有对数据库的底层操作。下面是示例代码段：<BR><BR>public void RunProc(string procName, out SqlDataReader dataReader) {<BR>SqlCommand cmd = CreateCommand(procName, null);<BR>dataReader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);<BR>}</P>
<P>　　我们看到了一个跟Duwamish截然不同的另一种数据访问方式，它将所有的数据访问方法抽象出来做成一个RunProc方法，至于返回数据呢，呵呵，它有点偷懒，直接返回一个DataReader给你，你自己去读吧。还记得Duwamish采用的层间数据传输载体是什么吗？对了，是DataSet，它被数据层填充后返回给了中间层。但是这里，数据层和传输层的数据传输载体变成了DataReader，实际上，还不能称它为数据载体，因为数据还没开始读呢，在这里，DataReader的作用和指针有点类似，也许我们应该称它为“数据引用”：）<BR><BR>　　接着往下看，DataReader被怎么“处理”的：<BR></P>
<P>public ProductResults[] GetList(string catid, int currentPage, int pageSize, ref int numResults) <BR>{<BR>numResults = 0;<BR>int index=0;<BR>SqlDataReader reader = GetList(catid);<BR>ProductResults[] results = new ProductResults[pageSize];<BR><BR>// now loop through the list and pull out items of the specified page<BR>int start = (int)((currentPage - 1) * pageSize);<BR>if (start &lt;= 0) start = 1;<BR><BR>// skip <BR>for (int i = 0; i &lt; start - 1; i++) {<BR>if (reader.Read()) numResults++;<BR>}<BR>if (start &gt; 1) reader.Read();<BR><BR>// read the data we are interested in<BR>while (reader.Read()) {<BR>if (index &lt; pageSize) {<BR>results[index] = new ProductResults();<BR>results[index].productid = reader.GetString(0);<BR>results[index].name =&nbsp;&nbsp;reader.GetString(1);<BR>index++;<BR>}<BR>numResults++;&nbsp;&nbsp; <BR>}<BR><BR>reader.Close();<BR><BR>// see if need to redim array<BR>if (index == pageSize)<BR>return results;<BR>else {<BR>// not a full page, redim array<BR>ProductResults[] results2 = new ProductResults[index];<BR>Array.Copy(results, results2, index);<BR>return results2;<BR>} <BR>}</P>
<P>　　注意到currentPage和pageSize了吗？原来在这里就进行了数据分页，只返回满足需要的最少的数据量，而不是象我们很多喜欢偷懒的人一样，简单的将整个DataTable一股脑的绑定到DataGrid，造成大量的数据冗余。<BR><BR>　　在这里，数据被真正的读出来，并且被手动填充到一个自定义的对象数组中，我们来看看这个数组的定义：<BR></P>
<P>public class ProductResults <BR>{<BR>private string m_productid;<BR>private string m_name;<BR><BR>// product props<BR>public string productid {<BR>get { return m_productid; }<BR>set { m_productid = value; }&nbsp;&nbsp;<BR>}<BR><BR>public string name {<BR>get { return m_name; }<BR>set { m_name = value; }&nbsp;&nbsp;<BR>}<BR>}</P>
<P>　　非常之简单，不过我有点奇怪为什么不使用struct呢？是不是.Net中struct和class的性能差距已经可以忽略不计了？<BR><BR>　　<B>分析总结</B><BR><BR>　　通过观察这两个商店的具体实现，我们得到了两个不同的数据访问模式，Duwamish采用的是以DataSet为核心，因为DataSet提供了这方面大量的相关方法，所以整个应用的数据传输，数据格式定义，数据校验都围绕着DataSet来进行，整个架构定义非常清晰和严谨，但是却显得有些庞大。PetShop在整个程序中没有采用一个DataSet，程序非常的简洁，轻灵，但是没有Duwamish那么强的健壮性。这两个程序是Microsoft公司不同的小组写出来的代码，所以有着不同风格。不过都应该能代表.Net的标准模式。看到这里，你应该对文章开头提出的那些疑问有一个比较形象的认识了吧。<BR><BR>　　另外，请再次注意，PetShop在打开数据连接之后，并没有马上读取数据，而是将DataReader传递给另外的对象来执行数据读的操作，然后才关闭连接。这样，数据连接的时间加长了，而数据库连接是一项非常宝贵的服务器资源，相比之下，Dawamish在连接数据库之后马上进行填充，然后迅速释放掉数据库连接的方式更加有利于大量用户的并发访问。<BR><BR>　　再一点，上文的程序中没有提到更新操作，PetShop采用的是使用Command对象执行单个存储过程的方式来进行更新操作，是属于一种在线即时数据更新模式。而Dawamish采用的是DataAdapter的Update方法，将DataSet的改变一次性的提交到数据库中，属于离线数据更新模式。这种模式的好处是可以一次性更新大批量数据，减少数据库的连接次数。缺点是如果数据库在改动非常频繁的情况下需要实时的跟踪数据变化就不合适了。需要根据具体的情况采用具体的数据更新办法。<BR><BR>　　总的来说，如果您只需要快速的读取数据并显示出来，推荐您采用DataReader，如果您需要对数据进行大量的修改，还有大量并发访问的可能，而且不需要实时的跟踪数据库的变化，推荐您使用DataSet。当然，这两种情况有点极端了，实际的应用环境也许有着很复杂的条件，具体需要您自己审时度势，综合采用，不过我个人还是比较喜欢PetShop那种轻灵的风格 ：）<BR><BR>　　本文只尝试对以上两个典型的.Net应用例程的数据访问机制做了一个简单的追踪分析。</P></TD></TR></TBODY></TABLE></DIV></TD></TR></TBODY></TABLE><img src ="http://www.cnitblog.com/oliver_yin/aggbug/5513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-12-17 17:17 <a href="http://www.cnitblog.com/oliver_yin/articles/5513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>突破Windows 2000/XP专业版IIS客户端连接限制</title><link>http://www.cnitblog.com/oliver_yin/articles/2400.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Mon, 29 Aug 2005 03:02:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/2400.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/2400.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/2400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/2400.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/2400.html</trackback:ping><description><![CDATA[<P align=center><B><SPAN class=main_ArticleTitle>突破Windows专业版IIS客户端连接限制方法</SPAN><BR></B><BR><SPAN class=px12line18>作者：admin　文章来源：本站原创　点击数：
<SCRIPT language=javascript src="/Article/GetHits.asp?ArticleID=215"></SCRIPT>
 71　更新时间：2005-5-14</SPAN></P><SPAN class=px14line21>
<DIV id=zoom><SPAN class=main_tdbg_760>
<P><FONT size=3>
<P><STRONG><FONT face=Arial size=2>突破Windows专业版IIS客户端连接限制方法<BR><BR></FONT></STRONG>突破Windows专业版IIS客户端连接限制方法<BR><BR>　　我们知道Windows 2000专业版或Windows XP专业版#作系统中IIS最多允许10个客户端的连接，在Windows 2000服务器版或Windows 2003服务器版#作系统中则不存在这种连接限制问题。<BR><BR>　　Microsoft提供了一个管理IIS的小工具MetaEdit，MetaEdit工作在Windows NT4.0 Windows 2000上，我发现它在Windows XP上也能正常工作，另外，MetaEdit只能管理II4.0、IIS5.0或更高版本的IIS。<BR><BR>　　下面教你如何利用这个工具突破Windows XP专业版IIS客户端连接限制：<BR><BR>　　首先，你需要到下面的地址下载MetaEdit，最新版本是2.2，地址：<A href="http://download.microsoft.com/do" target=_blank><FONT color=#003366>http://download.microsoft.com/do</FONT></A> ... /EN-US/MtaEdt22.exe。然后执行MtaEdt22.exe按向导提示完成安装。最后，在MetaEdit中设置客户端连接限制的参数。安装MetaEdit完毕后，在开始菜单的程序组Administrative Tools下点击MetaEdit 2.2运行，出现窗口：<BR><BR><BR><BR>　　在窗口的左边将树展开至LM W3SVC，直接在W3SVC文件夹上单击，选择右边列表中Name为MaxConnections的项，双击后，出现对话框：<BR><BR><BR><BR>　　在最后Data的文本框中默认的是10，这就是Windows XP专业版IIS默认设置的最大客户端连接数了，现在你可以改变这个默认值了，我把它改为10000，注意：在Win2000 上的IIS客户端连接数最大为2000000000。<BR><BR>　　关于这个工具我还未对Windows2000和Windows NT4下的IIS做过测试，有兴趣的朋友可以按上面的方法试一下。</P>
<P>软件下载地址有误，先更正如下：<BR><A href="http://download.microsoft.com/download/iis50/Utility/5.0/NT45/EN-US/MtaEdt22.exe" target=_blank><FONT color=#003366>http://download.microsoft.com/do ... /EN-US/MtaEdt22.exe</FONT></A><BR>如果上面的不能用，你就去网上搜索一下MtaEdt</P></FONT></SPAN></DIV></SPAN><img src ="http://www.cnitblog.com/oliver_yin/aggbug/2400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-08-29 11:02 <a href="http://www.cnitblog.com/oliver_yin/articles/2400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#如何在Form中嵌入并且操作Excel表格</title><link>http://www.cnitblog.com/oliver_yin/articles/2108.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Mon, 15 Aug 2005 08:48:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/2108.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/2108.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/2108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/2108.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/2108.html</trackback:ping><description><![CDATA[<DIV id=title>
<H2>C#如何在Form中嵌入并且操作Excel表格</H2></DIV>
<DIV id=date><SPAN>www.chinacs.net&nbsp;&nbsp;2004-08-10&nbsp;&nbsp;中文C#技术站</SPAN> </DIV>
<DIV id=main>
<DIV id=ad><BR>&nbsp;&nbsp;&nbsp; 网上比较多讲述如何操作Excel表的文章，但都是启动Excel的窗口来打开Excel数据文件。有时候需要把Excel表嵌入到自己程序的Form中，给客户一个不用切换窗口的操作界面，似乎更好。这在VC中用OLE技术很容易实现，但是在C#中方法就不一样啦。下面将就此进行阐述。</DIV>
<DIV id=content>
<P><STRONG>一、首先简要回顾一下如何操作Excel表</STRONG></P>
<P>&nbsp;&nbsp;先要添加对Excel的引用。选择项目-〉添加引用-〉COM-〉添加Microsoft Excel 9.0。（不同的office讲会有不同版本的dll文件）。<BR>&nbsp;&nbsp;&nbsp;using Excel;<BR>&nbsp;&nbsp;&nbsp;using System.Reflection;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;//产生一个Excel.Application的新进程<BR>&nbsp;&nbsp;&nbsp;Excel.Application app = new Excel.Application();<BR>&nbsp;&nbsp;&nbsp;if (app == null) <BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;statusBar1.Text = "ERROR: EXCEL couldn't be started!";<BR>&nbsp;&nbsp;&nbsp;&nbsp;return ;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;app.Visible = true; //如果只想用程序控制该excel而不想让用户操作时候，可以设置为false<BR>&nbsp;&nbsp;&nbsp;app.UserControl = true;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;Workbooks workbooks =app.Workbooks;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;_Workbook workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet); //根据模板产生新的workbook<BR>//&nbsp;&nbsp;_Workbook workbook = workbooks.Add("c:\\a.xls"); //或者根据绝对路径打开工作簿文件a.xls</P>
<P>&nbsp;&nbsp;&nbsp;Sheets sheets = workbook.Worksheets;<BR>&nbsp;&nbsp;&nbsp;_Worksheet worksheet = (_Worksheet) sheets.get_Item(1);<BR>&nbsp;&nbsp;&nbsp;if (worksheet == null) <BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;statusBar1.Text =&nbsp; "ERROR: worksheet == null";<BR>&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;// This paragraph puts the value 5 to the cell G1<BR>&nbsp;&nbsp;&nbsp;Range range1 = worksheet.get_Range("A1", Missing.Value);<BR>&nbsp;&nbsp;&nbsp;if (range1 == null) <BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;statusBar1.Text =&nbsp; "ERROR: range == null";<BR>&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;const int nCells = 2345;<BR>&nbsp;&nbsp;&nbsp;range1.Value2 = nCells;<BR>&nbsp;&nbsp;<BR><STRONG>二、将Excel用户界面嵌入到自己的Windows Form中</STRONG></P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于目前，C#和vb.net都不支持OLE技术(参见微软支持中心Info:304562)，，所以只有使用WebBrowser控件来完成此功能。（以下方法参见微软支持中心Howto:304662）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、右击工具箱，选择自定义工具箱，添加COM组件，选择“Microsoft Web 浏览器”（对应文件是\winnt\system32\shdocvw.dll），确定。在工具箱中将会出现文本为Explorer的WebBroser控件图标。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、在Form1中添加WebBrowser控件。（对象名却省是axWebBrowser1）<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、假定要打开的excel文件是: c:\a.xls。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;string strFileName = @"c:\a.xls";<BR>&nbsp;&nbsp;&nbsp;&nbsp; Object refmissing = System.Reflection.Missing.Value;<BR>&nbsp; &nbsp;&nbsp;&nbsp;axWebBrowser1.Navigate(strFileName, ref refmissing , ref refmissing , ref refmissing , ref refmissing);<BR>&nbsp;&nbsp;&nbsp;&nbsp;值得注意的是用WebBrowser控件不支持菜单合并，也就是说无法把Excel表的菜单带入到我们的程序中。这是相对于OLE实现方法的一大缺点。幸好提供了可以把工具栏添加进来的功能，通过工具栏可以进行许多Excel专有的操作。<BR>&nbsp; &nbsp;&nbsp;&nbsp;//下面这句可以将excel本身的工具调添加进来<BR>&nbsp;&nbsp;&nbsp; axWebBrowser1.ExecWB(SHDocVw.OLECMDID.OLECMDID_HIDETOOLBARS, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,ref refmissing , ref refmissing);<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR><STRONG>三、回到本文提出的问题，如何操作嵌入的Excel?</STRONG></P>
<P>&nbsp;&nbsp;&nbsp;首先需要明白，用WebBrowser“装载”Excel"表，实际上仍然是在新的进程空间中运行Excel.exe。可以用任务管理器观察。因此，只要我们能够获取Excel.Application对象，就能像上文一中所说的那样操作Excel数据。<BR>&nbsp;&nbsp;&nbsp;幸好可以通过WebBrowser的方法NavigateComplete提供的事件参数e来访问Excel.Application。<BR>&nbsp;&nbsp;public void axWebBrowser1_NavigateComplete2(object sender, AxSHDocVw.DWebBrowserEvents2_NavigateComplete2Event e)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;Object o = e.pDisp;<BR>&nbsp;&nbsp;&nbsp;Object oDocument = o.GetType().InvokeMember("Document",BindingFlags.GetProperty,null,o,null);<BR>&nbsp;&nbsp;&nbsp;Object oApplication = o.GetType().InvokeMember("Application",BindingFlags.GetProperty,null,oDocument,null);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Object oName = o.GetType().InvokeMember("Name",BindingFlags.GetProperty ,null,oApplication,null);</P>
<P>&nbsp;&nbsp;&nbsp;//由于打开的是excel文件，所以这里的oApplication 其实就是Excel.Application<BR>&nbsp;&nbsp;&nbsp;Excel.Application eApp =(Excel.Application)oApplication;//这样就可以象上文中所述来操作Excel了。<BR>&nbsp;&nbsp;}</P>
<P><STRONG>四、包含该WebBrowser的Form退出时候，如何确保Excel进程也退出</STRONG>？（参见Microsoft帮助中心KB317109）</P>
<P>&nbsp;&nbsp;由于WebBrowser只不过是对Excel表的浏览，而Excel在单独的进程中运行。所以要保证对该Excel对象eApp及其相应的所有成员变量都释放引用，才能保证在Form退出时excel进程跟着退出。这一点在一个程序需要多次打开关闭excel表时尤为重要。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Application oApp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Workbooks oBooks;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Workbook oBook;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Worksheet oSheet;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...........<BR>&nbsp;&nbsp;&nbsp; private void ExcelExit()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAR(oSheet);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oBook.Close(False);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAR(oBook);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAR(oBooks);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oApp.Quit();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAR(oApp);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.WriteLine("Sleeping...");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Threading.Thread.Sleep(5000);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Debug.WriteLine("End Excel");<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;private void NAR(Object o)<BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{System.Runtime.InteropServices.Marshal.ReleaseComObject(o);}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch{}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally{o = null;}<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;经过试验，我发现除了释放这些变量以外，必须把该axWebBroswer1也销毁掉，Excel进程才退出。否则的话，即使让axWebBroser1去Navigate空内容"about:blank", excel进程仍然不会退出。因此应该将axWebBroser1所在的Form关闭掉，或者直接调用axWebBrowser1.Dispose();<BR>&nbsp;&nbsp;如果还是其它问题导致不能正常退出，就只有调用垃圾回收了。<BR>&nbsp;&nbsp;GC.Collect();<BR></P></DIV></DIV><img src ="http://www.cnitblog.com/oliver_yin/aggbug/2108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-08-15 16:48 <a href="http://www.cnitblog.com/oliver_yin/articles/2108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DataSet调试利器</title><link>http://www.cnitblog.com/oliver_yin/articles/2104.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Mon, 15 Aug 2005 07:52:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/2104.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/2104.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/2104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/2104.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/2104.html</trackback:ping><description><![CDATA[<DIV align=center>
<H1 class=aTitle>codeproject上发现的DataSet调试利器</H1></DIV>
<DIV class=content id=BodyLabel style="PADDING-RIGHT: 10px; DISPLAY: block; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
<DIV class=postbody>调试DataSet时，如果要看到DataSet中的存储信息，通常需要把DataSet扔给一个DataGrid，等页面运行完了才可以知道，这样会使调试变得十分困难，特别是在有较多DataSet的情况下。<!--DVNEWS_AD_BEGIN-->
<SCRIPT type=text/javascript><!--
google_ad_client = "pub-4605890841814045";
google_ad_width = 336;
google_ad_height = 280;
google_ad_format = "336x280_as";
google_ad_type = "text_image";
google_ad_channel ="";
google_page_url = document.location;
//--></SCRIPT>

<SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript>
</SCRIPT>
 <!--DVNEWS_AD_END--><BR><BR>这两天无意中在codeproject上找到一个DSWatch，可以方便的在断点时，看到当前的DataSet情况。<BR><IMG src="http://www.csharp.net.cn/upload/2005_07/050729092127992.png" border=0><BR>DSWatch是以VS.net Addin的形式做的，大家安装好之后可以通过 外挂程序管理器 来设置是否加载它，默认情况下不加载，使用它只需要在Debug模式下，选中要调试的DataSet的名字，然后按鼠标右键，在弹出的菜单中会有DSWatch选项，选择它就可以了。<BR>DSWatch的下载地址<BR>源代码：<A href="http://www.codeproject.com/csharp/DSWatchEx/DSWatchEx_src.zip">http://www.codeproject.com/csharp/DSWatchEx/DSWatchEx_src.zip</A><BR>程序和演示：<A href="http://www.codeproject.com/csharp/DSWatchEx/DSWatchEx_demo.zip">http://www.codeproject.com/csharp/DSWatchEx/DSWatchEx_demo.zip</A><BR><BR><SPAN style="FONT-SIZE: 12pt">还有一个叫VS 2005 Debug Visualizer，是DSWatch的VS2005版本，支持对</SPAN><FONT size=2>&nbsp;<SPAN style="FONT-SIZE: 12pt">DataSet, DataTable, DataView, DataRow and DataColumn 进行实时调试。<BR><IMG src="http://www.csharp.net.cn/upload/2005_07/050729092127991.gif" border=0><BR>下载地址：<A href="http://www.codeproject.com/csharp/DataDebuggerVisualizer/DataDebuggerVisualizer_src.zip">http://www.codeproject.com/csharp/DataDebuggerVisualizer/DataDebuggerVisualizer_src.zip</A><BR></SPAN></FONT></DIV></DIV><img src ="http://www.cnitblog.com/oliver_yin/aggbug/2104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-08-15 15:52 <a href="http://www.cnitblog.com/oliver_yin/articles/2104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在WinForm程序中嵌入ASP.NET</title><link>http://www.cnitblog.com/oliver_yin/articles/1419.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Mon, 08 Aug 2005 08:48:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/1419.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/1419.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/1419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/1419.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/1419.html</trackback:ping><description><![CDATA[在WinForm程序中嵌入ASP.NET&nbsp; (转自<A href="http://www.blogcn.com/User8/flier_lu/blog/1125444.html">http://www.blogcn.com/User8/flier_lu/blog/1125444.html</A>)<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;现在的流行趋势是桌面程序Web化，Web程序桌面化，呵呵。最终目标就是你中有我，我中有你。例如MSN&nbsp;Explorer就是一个很好的展示，让用户在使用的时候分不清什么时候是在本地什么时候是在网络。而这类程序往往需要有一个后台服务器如IIS的支持，这对大多数桌面应用来说too&nbsp;heavy了。本着简单就是美的设计思想，这里给出一个轻量级的解决方法，把ASP.NET嵌入到普通WinForm桌面程序中去。<BR>&nbsp;&nbsp;&nbsp;因为安全以及其它一些方面的原因，在使用ASP.NET引擎之前，必须建立一个新的<A href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemAppDomainClassTopic.asp" target=_blank>AppDomain</A>。简单的方法是直接使用<A href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebhostingapplicationhostclasscreateapplicationhosttopic.asp" target=_blank>ApplicationHost.CreateApplicationHost</A>函数为指定的虚拟目录和物理路径建立ASP.NET引擎宿主的实例，如 
<P></P>
<P>&nbsp;//&nbsp;should&nbsp;create&nbsp;a&nbsp;subdirectory&nbsp;./bin&nbsp;and&nbsp;copy&nbsp;the&nbsp;assembly&nbsp;to&nbsp;it<BR>&nbsp;static&nbsp;public&nbsp;WebHost&nbsp;Create(string&nbsp;name,&nbsp;string&nbsp;path)<BR>&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;if(!name.StartsWith(new&nbsp;string(Path.AltDirectorySeparatorChar,&nbsp;1)))<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;=&nbsp;Path.AltDirectorySeparatorChar&nbsp;+&nbsp;name;<BR>&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;WebHost&nbsp;host&nbsp;=&nbsp;(WebHost)ApplicationHost.CreateApplicationHost(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typeof(WebHost),&nbsp;name,&nbsp;path);</P>
<P>&nbsp;&nbsp;&nbsp;host.setVirtualDirectory(name);<BR>&nbsp;&nbsp;&nbsp;host.setBaseDirectory(path);</P>
<P>&nbsp;&nbsp;&nbsp;return&nbsp;host;<BR>&nbsp;}</P>
<P>&nbsp;但这样建立的程序有个BT的要求，他会在指定目录的bin子目录中去尝试载入宿主类型(WebHost)的assembly，也就是说你必须把程序在bin子目录下复制一份，非常不爽。解决方法是自己手工完成整个建立过程，如下：</P>
<P>&nbsp;static&nbsp;public&nbsp;WebHost&nbsp;Create(string&nbsp;virtualDir,&nbsp;string&nbsp;physicalDir)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;if(!virtualDir.StartsWith(new&nbsp;string(Path.AltDirectorySeparatorChar,&nbsp;1)))<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtualDir&nbsp;=&nbsp;Path.AltDirectorySeparatorChar&nbsp;+&nbsp;virtualDir;<BR>&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;if(!physicalDir.EndsWith(new&nbsp;string(Path.DirectorySeparatorChar,&nbsp;1)))<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;physicalDir&nbsp;+=&nbsp;Path.DirectorySeparatorChar;<BR>&nbsp;&nbsp;&nbsp;}</P>
<P>&nbsp;&nbsp;&nbsp;AppDomainSetup&nbsp;setup&nbsp;=&nbsp;new&nbsp;AppDomainSetup();</P>
<P>&nbsp;&nbsp;&nbsp;setup.ApplicationName&nbsp;=&nbsp;"APP_"&nbsp;+&nbsp;Guid.NewGuid().ToString();<BR>&nbsp;&nbsp;&nbsp;setup.ConfigurationFile&nbsp;=&nbsp;"web.config";</P>
<P>&nbsp;&nbsp;&nbsp;AppDomain&nbsp;domain&nbsp;=&nbsp;AppDomain.CreateDomain("ASPHOST_"&nbsp;+&nbsp;Guid.NewGuid().ToString(),&nbsp;null,&nbsp;setup);<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".appDomain",&nbsp;"*");<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".appPath",&nbsp;physicalDir);<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".appVPath",&nbsp;virtualDir);<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".domainId",&nbsp;domain.FriendlyName);<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".hostingVirtualPath",&nbsp;virtualDir);<BR>&nbsp;&nbsp;&nbsp;domain.SetData(".hostingInstallDir",&nbsp;HttpRuntime.AspInstallDirectory);</P>
<P>&nbsp;&nbsp;&nbsp;WebHost&nbsp;host&nbsp;=&nbsp;(WebHost)domain.CreateInstanceAndUnwrap(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typeof(WebHost).Module.Assembly.FullName,&nbsp;typeof(WebHost).FullName);</P>
<P>&nbsp;&nbsp;&nbsp;host.setApplicationDomain(domain);<BR>&nbsp;&nbsp;&nbsp;host.setVirtualDirectory(virtualDir);<BR>&nbsp;&nbsp;&nbsp;host.setBaseDirectory(physicalDir);</P>
<P>&nbsp;&nbsp;&nbsp;return&nbsp;host;</P>
<P>&nbsp;}</P>
<P>&nbsp;这儿的一堆domain.SetData是传递参数给ASP.NET引擎。然后在那个appdomain中建立新的宿主类型的实例。这样就避免多份代码的尴尬。而使用ASP.NET就比较简单了，在宿主类中使用<A href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemWebHttpRuntimeClassProcessRequestTopic.asp" target=_blank>HttpRuntime.ProcessRequest</A>函数处理特定请求。简单一点的话，可以直接用<A href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemWebHostingSimpleWorkerRequestClassTopic.asp" target=_blank>SimpleWorkerRequest</A>包装请求，生成页面到一个指定的TextWriter中，如</P>
<P>&nbsp;private&nbsp;void&nbsp;DoRequest(string&nbsp;page,&nbsp;string&nbsp;query,&nbsp;TextWriter&nbsp;writer)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;HttpRuntime.ProcessRequest(new&nbsp;SimpleWorkerRequest(page,&nbsp;query,&nbsp;writer));<BR>&nbsp;}</P>
<P>&nbsp;public&nbsp;void&nbsp;RequestPage(string&nbsp;page,&nbsp;string&nbsp;query,&nbsp;Stream&nbsp;stream)<BR>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;DoRequest(page,&nbsp;query,&nbsp;new&nbsp;StreamWriter(stream));<BR>&nbsp;}</P>
<P>&nbsp;public&nbsp;void&nbsp;RequestPage(string&nbsp;page,&nbsp;Stream&nbsp;stream)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;RequestPage(page,&nbsp;null,&nbsp;stream);<BR>&nbsp;}</P>
<P>&nbsp;public&nbsp;string&nbsp;RequestPage(string&nbsp;page,&nbsp;string&nbsp;query)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;using(StringWriter&nbsp;writer&nbsp;=&nbsp;new&nbsp;StringWriter())&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoRequest(page,&nbsp;query,&nbsp;writer);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;writer.ToString();<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;}</P>
<P>&nbsp;public&nbsp;string&nbsp;RequestPage(string&nbsp;page)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;return&nbsp;RequestPage(page,&nbsp;string.Empty);<BR>&nbsp;}</P>
<P>&nbsp;这个缺省的请求包装使用是简单，但对中文的兼容性不太好，过两天有空再自己写个强一点的吧，呵呵</P>
<P>&nbsp;最终类的使用就比较简单了，在WinForm程序中建立一个singleton模式的属性</P>
<P>&nbsp;static&nbsp;private&nbsp;WebHost.WebHost&nbsp;_host&nbsp;=&nbsp;null;</P>
<P>&nbsp;public&nbsp;WebHost.WebHost&nbsp;Host<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp;get<BR>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(_host&nbsp;==&nbsp;null)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_host&nbsp;=&nbsp;WebHost.WebHost.Create();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;_host;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;}</P>
<P>&nbsp;然后请求指定的asp.net页面，如</P>
<P>&nbsp;HTML&nbsp;=&nbsp;Host.RequestPage(_page);</P>
<P>&nbsp;即可完成从动态的asp.net脚本到静态html的转换。嵌入WinForm程序中，还可以通过Host类型完成两者之间的双向通讯，实现互相控制。下次有空继续，呵呵</P>
<P>&nbsp;参考资料：<BR>&nbsp;&nbsp;&nbsp;1.Using&nbsp;the&nbsp;ASP.Net&nbsp;Runtime&nbsp;for&nbsp;extending&nbsp;desktop&nbsp;applications&nbsp;with&nbsp;dynamic&nbsp;HTML&nbsp;Scripts<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.asp" target=_blank>http://www.west-wind.com/presentations/aspnetruntime/aspnetruntime.asp</A> </P>
<P>&nbsp;&nbsp;&nbsp;2.Executing&nbsp;ASMX&nbsp;files&nbsp;without&nbsp;a&nbsp;web&nbsp;server&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://radio.weblogs.com/0105476/stories/2002/10/24/executingAsmxFilesWithoutAWebServer.html" target=_blank>http://radio.weblogs.com/0105476/stories/2002/10/24/executingAsmxFilesWithoutAWebServer.html</A> </P>
<P>&nbsp;&nbsp;&nbsp;3.ASP.&nbsp;NET&nbsp;Client-side&nbsp;Hosting&nbsp;with&nbsp;Cassini<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://msdn.microsoft.com/msdnmag/issues/03/01/CuttingEdge/" target=_blank>http://msdn.microsoft.com/msdnmag/issues/03/01/CuttingEdge/</A> </P>
<P>&nbsp;&nbsp;&nbsp;4.Using&nbsp;ASP.NET&nbsp;Runtime&nbsp;in&nbsp;Desktop&nbsp;Applications&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<IMG alt=::URL:: hspace=2 src="http://www.blogcn.com/images/aurl.gif" align=absBottom border=0><A href="http://www.codeguru.com/cs_internet/UsingAspRuntime.html" target=_blank>http://www.codeguru.com/cs_internet/UsingAspRuntime.html</A> <BR></P><img src ="http://www.cnitblog.com/oliver_yin/aggbug/1419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-08-08 16:48 <a href="http://www.cnitblog.com/oliver_yin/articles/1419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样解决 Object reference not set to an instance of an object.</title><link>http://www.cnitblog.com/oliver_yin/articles/1417.html</link><dc:creator>生活像一团麻</dc:creator><author>生活像一团麻</author><pubDate>Mon, 08 Aug 2005 08:36:00 GMT</pubDate><guid>http://www.cnitblog.com/oliver_yin/articles/1417.html</guid><wfw:comment>http://www.cnitblog.com/oliver_yin/comments/1417.html</wfw:comment><comments>http://www.cnitblog.com/oliver_yin/articles/1417.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnitblog.com/oliver_yin/comments/commentRss/1417.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/oliver_yin/services/trackbacks/1417.html</trackback:ping><description><![CDATA[<P>参看网址：<BR></P><A href="http://support.microsoft.com/?scid=kb;zh-cn;810245&amp;spid=3039&amp;sid=global">http://support.microsoft.com/?scid=kb;zh-cn;810245&amp;spid=3039&amp;sid=global</A><BR><BR>
<H1 class=title>FIX：ASP 会话状态中的无效对象</H1>
<DIV class=appliesToLink><A href="http://support.microsoft.com/?scid=kb;zh-cn;810245&amp;spid=3039&amp;sid=global#appliesto">察看本文应用于的产品</A></DIV>
<DIV class=articleProperty>
<TABLE>
<TBODY>
<TR>
<TD class=label>文章编号</TD>
<TD class=text>:</TD>
<TD class=text>810245</TD></TR>
<TR>
<TD class=label>最后修改</TD>
<TD class=text>:</TD>
<TD class=text>2003年6月9日</TD></TR>
<TR>
<TD class=label>修订</TD>
<TD class=text>:</TD>
<TD class=text>1.0</TD></TR></TBODY></TABLE></DIV>
<DIV class=section><A id=kb1></A>
<H2 class=subTitle>症状</H2>
<DIV class=sbody>连接 .NET 的 Web 应用程序在会话状态中存储一个对象。当您让此应用程序空闲 12 到 20 分钟，然后再次尝试访问该对象时，您可能会收到一条指出发生了无效对象异常的错误消息，如下所示： 
<DIV class=errormsg>Server Error in '/TheTest Application' Application.<BR><BR>Object reference not set to an instance of an object.<BR><BR>Description:An unhandled exception occurred during the execution of the current web request.Please review the stack trace for more information about the error and where it originated in the code.<BR><BR>Exception Details:System.NullReferenceException:Object reference not set to an instance of an object.</DIV></DIV><A id=kb2></A>
<H2 class=subTitle>解决方案</H2>
<DIV class=sbody>现在，您可以从 Microsoft 获得支持的修复程序，但它仅用于纠正本文所述的问题。只将它应用于出现这一特定问题的系统。<BR><BR><B>注意</B> 您必须有 Visual Studio 许可协议才能获得此修复程序。<BR><BR>要想解决此问题，请与 Microsoft 产品支持服务联系以获得该修补程序。有关 Microsoft 产品支持服务电话号码和支持费用信息的完整列表，请访问下面的 Microsoft Web 站点： 
<DIV class=indent><A href="http://support.microsoft.com/default.aspx?scid=fh;en-us;cntactms">http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS</A><SPAN class=pLink> (http://support.microsoft.com/default.aspx?scid=fh;en-us;cntactms)</SPAN></DIV><B>注意</B> 特殊情况下，如果 Microsoft 支持专业人员确定只有专门更新才能解决您的问题，可免收支持电话的费用。对于不需要进行专门更新的问题以及其他支持查询，将正常收取费用。 <BR></DIV></DIV>
<DIV class=appliesTo>
<HR>
<A id=appliesto></A>
<H5>这篇文章中的信息适用于:</H5>
<TABLE class=list>
<TBODY>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET 2002 专业版</TD></TR>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET (2002), Professional Edition SP1</TD></TR>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET 2002 企业级结构设计版</TD></TR>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET (2002), Enterprise Architect Edition SP1</TD></TR>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET 2002 企业级开发版</TD></TR>
<TR>
<TD class=bullet>•</TD>
<TD class=text>Microsoft Visual Studio .NET (2002), Enterprise Developer Edition SP1</TD></TR></TBODY></TABLE></DIV>
<DIV class=topOfPage>
<TABLE>
<TBODY>
<TR>
<TD class=image><A href="http://support.microsoft.com/?scid=kb;zh-cn;810245&amp;spid=3039&amp;sid=global#top"><IMG title=回到顶端 alt=回到顶端 src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"></A></TD>
<TD class=text><A href="http://support.microsoft.com/?scid=kb;zh-cn;810245&amp;spid=3039&amp;sid=global#top">回到顶端</A></TD></TR></TBODY></TABLE></DIV><img src ="http://www.cnitblog.com/oliver_yin/aggbug/1417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/oliver_yin/" target="_blank">生活像一团麻</a> 2005-08-08 16:36 <a href="http://www.cnitblog.com/oliver_yin/articles/1417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>