﻿<?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>BlogJava-kapok-随笔分类-程序员生活</title><link>http://www2.blogjava.net/kapok/category/768.html</link><description>垃圾桶,嘿嘿，我藏的这么深你们还能找到啊，真牛！</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:28:34 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:28:34 GMT</pubDate><ttl>60</ttl><item><title>印度项目质量管理经验 </title><link>http://www.blogjava.net/kapok/archive/2005/04/15/3318.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Fri, 15 Apr 2005 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/15/3318.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3318.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/15/3318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3318.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3318.html</trackback:ping><description><![CDATA[原文出处：<A href="http://www.yesky.com/20030325/1659121.shtml"><FONT size=3>http://www.yesky.com/20030325/1659121.shtml</FONT></A><BR><BR><BR><FONT size=4>　　计算机和通信技术的迅速发展，特别是Internet技术的发展与普及，为企业内部、企业与外部提供了快速、准确、可靠的信息交流渠道。信息化企业运作管理系统已成为企事业单位参与全球市场竞争的必备支持系统。正是由于这样的市场需求与技术发展现状，为我国的IT行业带来了空前发展的机遇，特别是软件行业。软件企业能否抓住这样一个难得的发展机会需要多方面的努力，其中软件质量保障在其发展过程中占有重要的位置。 众所周知，印度已成为世界上软件业增长最快的国家，目前每年软件业产值达数十亿美元，并且还在以每年30%～50%的速度增长。比较我国和印度的软件产业，就不难发现:中国拥有巨大的软件市场和世界公认的软件开发资源，在基础研究和对技术前瞻性的把握上，也有自己的优势，就整体社会经济环境而言也优于印度。此外，中国的软件开发人员费用比较低廉，仅是世界市场的1/3左右。虽然中国人并不缺乏软件开发的天赋，但是在越来越强调规模化经营的今天，先天不足的管理痼疾使我们举步维艰，难以摆脱小作坊式的软件开发模式。而印度软件业从一开始就立足于为美国软件企业服务，并遵循其软件开发的管理模式，与国际标准接轨。 </FONT>
<P><FONT size=4>　　管理上的问题不能得到彻底的解决，软件的质量保障就无从谈起。笔者最近在与印度一家通过了CMM4级评估的软件公司（以下简称A公司）进行合作的过程中，较为详细地了解了他们有关项目管理的一些详细情况，更深刻地感受到了项目管理的规范化与企业软件质量保障之间的密切关系。下面想着重从软件企业的构架，软件项目计划、项目管理、项目经理的职责等方面对印度软件的项目管理及我国软件质量保障应注意的问题进行一些经验总结，供业内人士参考。<BR>&nbsp;<BR>　　1.软件企业的组织结构 </FONT></P>
<P><FONT size=4>　　(1)A公司结构 </FONT></P>
<P><FONT size=4>　　图1是A公司的组织结构图，同国内公司差异较大的部门有QA、SSG和人力资源部门。 </FONT></P>
<P><FONT size=4></FONT>
<CENTER><FONT size=4><IMG height=262 src="http://www.yesky.com/20030325/softjt2030325_1.jpg" width=400><BR><BR>图1 </FONT></CENTER>
<P><FONT size=4></FONT></P>
<P><FONT size=4>　　* A公司中，QA(Quality Assure)部门与研发部门独立，负责监督流程的执行。QA同时负责领导与研发部门组成的联合工作组，制定公司流程。 <BR>　　* SSG(System Support Group)类似我们的IT部门，负责公司所有计算机软件和硬件资源的分配和管理。所有的办公环境和开发/实验室环境由SSG负责安装和维护，计算机资源属于SSG，由各个项目向SSG提出需求，项目结束后，设备需要交还给SSG。个人和项目组没有固定的软件和硬件资源。SSG是与研发平行的部门。 <BR>　　* 人力资源部门负责公司的人力资源管理，并维护员工的技能数据库。项目开始时，项目组向人力资源申请人力，向SSG申请计算机硬件和软件。项目结束时需要释放计算机资源给SSG，释放人力资源到人力资源池，并同时更新员工的技能数据库。研发部门的人力资源由研发总负责人和其助手分配(类似我国各公司的人力资源部)。 </FONT></P>
<P><FONT size=4>　　(2)项目组结构 </FONT></P>
<P><FONT size=4>　　1) A公司对项目组进行独立核算，项目具体负责人为PC(Project Coordinator)，负责项目计划和执行，对项目具体成员进行分工。在每个阶段的结束会议上(如概要设计结束)，PC要接受QC(Quality Coordinator)的审查。除了PC与QC的接口外，所有其他外部接口都由EM(Engineer Manager)完成，EM负责与客户打交道，向SSG、人力资源要求资源，与其他项目组协调进度。<BR>&nbsp;<BR>　　2) 汇报关系为: <BR>　　Team Member-&gt;Team Leader-&gt;PC-&gt;EM-&gt;研发总负责人。 </FONT></P>
<P><FONT size=4>　　3) 印度工程师分为7级，半年一次考评，即半年有一次升级机会。 <BR>　　1级:Software Engineer，刚毕业的本科生和研究生。 <BR>　　2级:Senior Software Engineer。 <BR>　　3级:Project Leader。 <BR>　　4级:Project Manager。 <BR>　　5级:Senior Project Manager。 <BR>　　3级可以成为PC，4级可以成为EM。刚开始平均2年升一级，越往后升职越慢。 </FONT></P>
<P><FONT size=4>　　A公司规定，一人最多可以同时兼任两个项目的PC，EM管理的项目没有限制。 </FONT></P>
<P><FONT size=4>　　A公司通常的项目组为4到5人，最多不超过10人。 </FONT></P>
<P><FONT size=4>　　以上是A公司（同时也是印度大多数规范化的软件公司）的组织结构和项目组结构。可以看出，A公司的组织结构非常清晰，各个部门分类非常细，任务明确，软件生产的每一个步骤都有专门的部门、专门的人员负责，从最基础的开发人员到负责统领全局的总经理，层层管理，沟通渠道畅通。而在我国，管理的不规范往往首先体现在公司的组织结构上，集中表现为部门的缺失和管理的交叉上。我国的软件公司，大部分规模较小，开发人员超过100人的公司很少。在印度，软件公司无论大小，都是“麻雀虽小，五脏俱全”，绝不会因为公司的规模大小而改变合理的组织结构。因此笔者认为，国内的软件企业要想有效地保障产品质量，首先就要在构架合理的组织结构上下功夫，这就如同盖高楼首先要打好地基一样，地基不打牢，结构不合理，其他方面再下功夫也是徒劳。有人说，因为国内软件企业规模小，所以造成结构设置的欠缺，但笔者认为恰恰是因为没有建立一个规范化的组织结构，才会使软件产品质量不保，进而严重影响了企业的发展扩大。 </FONT></P>
<P><FONT size=4>　　2.项目计划 </FONT></P>
<P><FONT size=4>　　凡事预则立，不预则废。这里的“预”就是指计划。对于软件企业，计划的重要性是不言而喻的。让我们先看看A公司的项目计划是如何制定的:在A公司，项目开始之前必须先估计项目的规模（以代码行数来衡量）;然后制定项目计划。通常时间为2～3周，已知的最长有5周。EM负责制定项目 EWP(Engineer Work Paper)，其中定义了项目需要的人力和计算机资源，由相关部门同意，并报研发总负责人批准后才能开始项目。 </FONT></P>
<P><FONT size=4>　　项目的正式开始时间由项目组的Kickoff Meeting算起，Closeout Meeting结束。 </FONT></P>
<P><FONT size=4>　　大概很多人都听过这样一句话：“计划赶不上变化”。这种“变化”对某些行业而言也许并不会产生太大的影响，但对于软件企业而言，却会给软件产品的质量保证带来严重的负面影响。为什么会造成这种“计划赶不上变化”的现象？究其原因，笔者认为主要是因为对计划的重视程度不够，计划过于笼统、粗糙导致可执行性太差，再加上一些人为因素的影响，必然会产生这样的后果。 </FONT></P>
<P><FONT size=4>　　如果我们的软件企业都能像A公司这样，在作计划时能考虑到每一个细节，不是仓促做出决定，而是由所有的相关部门共同对产品计划进行反复研究、制定、讨论、修改，最终形成一套系统、严密、具有很强的可执行性的计划。计划一旦形成，就严格按照计划去执行，而不受某个人、某件事的影响，那么就不仅能够减少大量资源的浪费，产品的质量也得到了保障。 </FONT></P>
<P><FONT size=4>　　因此，对计划的高度重视、周密制定、严格执行是企业有效保障产品质量的一个重要环节。 </FONT></P>
<P><FONT size=4>　　3.项目管理 </FONT></P>
<P><FONT size=4>　　当企业构架了合理的组织结构并制定了缜密的计划后，就进入了产品的开发阶段。在这个阶段中，项目管理起了重要作用，它所涉及的环节相当具体复杂，下面先介绍一下A公司在项目管理上的具体细节： </FONT></P>
<P><FONT size=4>　　(1)开发阶段和项目周期 <BR>　　开发阶段比较明显，注重各阶段应完成的功能，对本阶段应完成的工作不能留到下一阶段。<BR>&nbsp;<BR>　　(2)流程 </FONT></P>
<P><FONT size=4>　　* A公司对流程比对项目更重视。 <BR>　　* 软件开发流程非常规范和系统化，其流程的可执行性很高，并且能在实践过程中不断改进。A公司的流程已覆盖到了一个项目研发的所有方面，包括从最开始的意向到最后软件的版本发布(release)，都有相应的流程规定，基本上已形成一种工业化的软件开发。 <BR>　　* 人和流程是保证项目成功的两个最关键因素。由好的人按好的流程进行项目开发，才能最大限度地保证项目的成功。一个好的流程可以保证差的人做出来的东西不至于太差，但不能确保做出精品。通过流程可以实现一种规范化、流水线化、工业化的软件开发。 </FONT></P>
<P><FONT size=4>　　(3)计划 </FONT></P>
<P><FONT size=4>　　1) 计划详细、周到。 </FONT></P>
<P><FONT size=4>　　2) 流程中明确定义开发阶段。<BR>&nbsp;<BR>　　3) 每个阶段都列出了该阶段的各项活动，并详细描述每项活动的属性: <BR>　　* 进入条件，输入; <BR>　　* 验证方法; <BR>　　* 结束条件，输出。 </FONT></P>
<P><FONT size=4>　　4)每个阶段结束都要召开阶段结束会议。前一个阶段结束才能进入下一阶段。 </FONT></P>
<P><FONT size=4>　　5)计划中每个活动都比较具体，每个活动的时间以天（半天）为单位。计划包括了开展质量控制活动的时间。 </FONT></P>
<P><FONT size=4>　　(4)Review </FONT></P>
<P><FONT size=4>　　按印度公司流程，一般把Review和测试作为保证软件质量两个主要手段。测试的重要性就不需说明了，而Review则是一个非常简单有效并能尽早发现软件中错误的方法，可以说，任何交付物都要经Review后才能进行基线化。目前A公司有很详细全面、可执行性很高的Review流程和各种交付物的Review Checklist。 </FONT></P>
<P><FONT size=4>　　在印度软件企业，现有这么一句口号：凡事有计划，凡事必review。 </FONT></P>
<P><FONT size=4>　　(5)QA </FONT></P>
<P><FONT size=4>　　QC（质量经理）作为质量保证部门（SQA）的代表，监督和保证项目的进展遵循QMS各项流程和模板，并且收集项目中发现的一些问题和解决方法以优化流程。 </FONT></P>
<P><FONT size=4>　　(6)度量数据 </FONT></P>
<P><FONT size=4>　　CMM中比较强调用数据说话，对项目过程中基本上所有的数据都会有记录，最后把收集的数据提交质量保证部门进行分析，以改进流程。A公司的项目经理和质量经理很重视项目中的数据收集，包括各种Review数据、测试数据以及项目组员每天的活动数据等。项目经理也要维护一个项目档案，在这个项目档案中可以说包含了项目开发过程中所有的产出、开发活动、管理活动等的记录。可以这么说，有了这个项目档案，你就可以完全了解这个项目的开发过程。 </FONT></P>
<P><FONT size=4>　　(7)团队精神 </FONT></P>
<P><FONT size=4>　　印度公司都比较强调团队精神、合作精神，应该说，其流程本质上就要求员工之间的互相协调和理解。相对而言，印度员工的合作精神和协调精神都比我国员工要好得多。</FONT></P>
<P><FONT size=4>　　(8)培训 </FONT></P>
<P><FONT size=4>　　印度公司都比较强调培训，一般有专门的培训部门进行协调。在新员工进入公司后都会有公司流程和其他一些公司普遍章程的培训，以保证员工对流程的理解和执行。对于具体项目，项目经理在制定项目计划时就会在项目计划中提出所有的培训需求，包括技术上的培训和其他所需的培训。 </FONT></P>
<P><FONT size=4>　　(9)配置管理 <BR>　　在项目正式开展前，项目经理就要制定配置管理计划，并且指定配置管理员建立起配置管理库，按配置流程严格进行配置管理。在配置流程中也详细提供了对更改的控制，没有经过批准的更改请求是绝对不能进行的。 <BR>　　(10)记录 </FONT></P>
<P><FONT size=4>　　记录及时、充分、比较准确。这些记录包括:重要的邮件、会议纪要、审核记录、缺陷报告、测试报告。<BR>&nbsp;<BR>　　1)与客户和其他项目组的所有往来必须邮件记录。 </FONT></P>
<P><FONT size=4>　　2)对所有的活动都有一个跟踪落实的过程，比如对所有的Review记录和更改请求都会有一个状态标识，标识其当前状态，通过跟踪其状态来监督其落实。 </FONT></P>
<P><FONT size=4>　　3)对所有的活动，包括对文档和代码的更改都会有一个历史记录。 </FONT></P>
<P><FONT size=4>　　4)记录比较准确、比较客观。 </FONT></P>
<P><FONT size=4>　　5)许多记录都是通过定量的数值记录，强调以数据说话（CMM4级的重点就是量化管理）。 </FONT></P>
<P><FONT size=4>　　以上是A公司在项目管理中所涉及到的一些主要环节，很值得国内的软件企业在制定项目管理规划时借鉴。除此之外，我国的软件企业在产品开发管理的过程中，还易出现以下几个方面的问题: </FONT></P>
<P><FONT size=4>　　1)需求说明差─需求不清楚、不完整、太概括、或者不可测试，都会造成问题。 </FONT></P>
<P><FONT size=4>　　2)不切实际的时间表─如果在很短的时间里要求做许多事，出现错误是不可避免的。 </FONT></P>
<P><FONT size=4>　　3)测试不充分─只能根据客户意见或系统崩溃来判断系统的质量。 </FONT></P>
<P><FONT size=4>　　4)不断增加功能─在开发正在进行过程中要求增加许多新的功能。这是常见的问题。 </FONT></P>
<P><FONT size=4>　　5)交流问题─如果开发人员对客户的要求不了解，或者客户由不恰当的期望，必然会导致错误。<BR>&nbsp;<BR>　　这些问题的出现，将会对软件质量的保证产生不良影响，针对上述问题并结合A公司在项目管理方面的经验，笔者提出一些相应的解决方法，以供参考： </FONT></P>
<P><FONT size=4>　　1)可靠的需求─应当有一个经各方一致同意的、清楚的、完整的、详细的、整体的、可实现的、可测试的需求。为帮助确定需求，可使用模型 (prototypes)。 </FONT></P>
<P><FONT size=4>　　2）合理的时间表――为计划、设计、测试、改错、再测试、变更、以及编制文档留出足够的时间。不应使用突击的办法来完成项目。 </FONT></P>
<P><FONT size=4>　　3)适当测试─尽早开始测试；每次改错或变更后，都应重新测试。项目计划中要为测试和改错留出足够时间。 </FONT></P>
<P><FONT size=4>　　4)尽可能坚持最初的需求─一旦开发工作开始，要准备防止修改需求和新增功能，要说明这样做的后果。如果必须进行变更，必须在时间表上有相应的反映。如果可能，在设计阶段使用快速的模型，以便使客户了解将会得到的东西。这将会使他们对他们的需求有较高的信心，减少以后的变更。 </FONT></P>
<P><FONT size=4>　　5)沟通――在适当时机进行预排和检查;充分利用团组通信工具―电子邮件、群件(groupware)、网络故障跟踪工具、变更管理工具、以及因特网的功能。要确保文件是可用的和最新的。优选电子版文档，避免纸介质文档:进行远距离联合作业及协作;尽早使用模型，使客户的预想表达清楚。 </FONT></P>
<P><FONT size=4>　　4.PC（项目经理） </FONT></P>
<P><FONT size=4>　　项目经理是项目成败的关键人物，其对项目的成败负主要责任。因此在这里将项目经理的有关内容单独提出，以A公司为例详细说明PC在整个产品研发过程中所扮演的角色，希望能对国内软件企业的项目经理有所启示。 </FONT></P>
<P><FONT size=4>　　（1)在A公司，按流程在一个项目正式开展之前，项目经理需要完成： </FONT></P>
<P><FONT size=4>　　* 项目计划(Project Plan):在此描述整个项目所应完成的交付物、项目时间表、培训需求、资源需求、质量保证计划以及过程和交付物的定量质量目标等。 </FONT></P>
<P><FONT size=4>　　* 项目配置管理计划(Project Configuration Plan):在此指定配置管理员，描述项目配置项列表、配置管理库、版本管理计划等等。 </FONT></P>
<P><FONT size=4>　　*项目过程手册(Process Handbook):在此描述本项目所采取的裁剪后的生命周期模型和流程。 </FONT></P>
<P><FONT size=4>　　（2）在项目开发过程中，项目经理需非常了解项目进度，进行工作任务细化、具体计划和安排项目成员工作任务等工作。对突发事件项目经理需能及时合理地进行协调。 </FONT></P>
<P><FONT size=4>　　（3)总的说来，PC安排工作有这么几个特点: </FONT></P>
<P><FONT size=4>　　a.PC对软件开发具有丰富的经验，了解软件开发的普遍流程，了解各个阶段所需完成的工作，这是安排好项目组成员工作的前提，在A公司对PC的整体素质要求非常高。 </FONT></P>
<P><FONT size=4>　　b.在项目正式开展前，PC准备项目计划文档，在项目计划中包含了项目进度时间表，但此时间表比较粗，只能给出各个阶段和各个子阶段的起始结束日期。对各个阶段和各个子阶段的详细工作安排和各项工作责任人只能在项目开展工程中根据项目实际情况进行安排，一般是在每周项目组例会上进行本周详细工作安排。<BR>&nbsp;<BR>　　c.PC对工作安排往往精确到天，有时甚至精确到小时，要做到这一点，需要: </FONT></P>
<P><FONT size=4>　　* PC对本项目进展非常了解。了解渠道通常是每周组员的状态报告和直接与组员接触了解，这也需项目组成员能如实汇报工作。 </FONT></P>
<P><FONT size=4>　　* 对现阶段或本周所需完成的工作非常了解。知道现在该做什么，并且能把各项工作进行合理细致地划分，因为各个分解的工作比较细致，因此能相对精确地评估出这些工作完成所需的时间。 </FONT></P>
<P><FONT size=4>　　* PC对项目组员的能力比较了解，安排工作时能做到有的放矢。当安排的员工对工作不熟悉时，会指定相应的组员进行协助。 </FONT></P>
<P><FONT size=4>　　* PC对组员的工作安排都比较细致饱满。一般不会出现有些员工有事干，有些员工没事干的情况，当出现这种情况或员工提前完成工作时，PC就会进行相应的协调。 </FONT></P>
<P><FONT size=4>　　d.PC在项目组例会上的工作安排一般只限于本周或甚至是过后的二、三天，一般不会太长，对长时间工作的安排容易失去精确并且不易控制。相对而言，短时间的工作安排就比较精确而且容易控制，并且能不断根据完成的工作进行调整。当然，这就要求PC能根据项目计划中的项目时间表进行整体进度的把握。</FONT></P>
<P><FONT size=4>　　e.项目组例会一般一周一次（时间不能太长），但必要时（如组员工作已完成或其他事情），也可在中途召开项目会议进行工作安排，一般时间都比较短（十几分钟左右，一般不超过半小时，以免浪费时间），总之，当PC觉得需要时，就会召开项目会议。 </FONT></P>
<P><FONT size=4>　　f.当项目组出现意外事件或影响项目团结的事件时，PC能及时合理协调，解决项目组内的不和谐气氛。<BR>&nbsp;<BR>　　g.PC善于鼓励手下，发挥员工的潜能，PC往往会赞扬很好地完成了工作的组员。<BR>&nbsp;<BR>　　从上面可以看出，对PC的能力（包括技术和管理能力）要求是非常高的，我国的软件企业往往只重视PC的技术能力，但事实上，一个只精通技术的人往往不能成为一个合格的领导者， 笔者认为对PC而言，首先要求他能够比他的下属看得更远一步，顺利时不盲目乐观，遇到挫折时不茫然失措，使整个团队始终保持高昂的士气。<BR><BR>　　<STRONG>总结</STRONG></FONT></P>
<P><FONT size=4>　　以上结合印度软件项目管理的经验总结了一些我国软件质量保障应注意的问题。曾有人提出:这样一味地学习模仿，民族软件工业没有多大希望。但笔者认为，在这个问题上不妨采取“拿来主义”的办法，对于好的，事实证明是成功的经验，首先是“占有”，然后才是“挑选”和“创新”。如果能把印度的管理经验真正领会并付诸实践，相信对我们的民族软件工业一定会起到积极的推动作用。</FONT></P><img src ="http://www.blogjava.net/kapok/aggbug/3318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-15 15:50 <a href="http://www.blogjava.net/kapok/archive/2005/04/15/3318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单记录以下。论文用</title><link>http://www.blogjava.net/kapok/archive/2005/04/13/3134.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Wed, 13 Apr 2005 05:40:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/13/3134.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3134.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/13/3134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3134.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3134.html</trackback:ping><description><![CDATA[<A href="http://www.cnblogs.com/William_Fire/articles/125108.html">http://www.cnblogs.com/William_Fire/articles/125108.html</A><BR><BR><A href="http://www.cnblogs.com/William_Fire/articles/125819.html">http://www.cnblogs.com/William_Fire/articles/125819.html</A><BR><BR><BR><BR><A href="http://www.cnblogs.com/william_fire/articles/126665.html">http://www.cnblogs.com/william_fire/articles/126665.html</A><A href="http://www.cnblogs.com/william_fire/articles/126665.html"></A><BR><A href="http://www.cnblogs.com/tintown/archive/2005/03/23/124395.html">http://www.cnblogs.com/tintown/archive/2005/03/23/124395.html</A><BR><BR><BR><A href="http://www.cnblogs.com/tintown/category/12787.html">http://www.cnblogs.com/tintown/category/12787.html</A><BR><A href="http://www.cnblogs.com/tintown/archive/2005/04/04/131784.html">http://www.cnblogs.com/tintown/archive/2005/04/04/131784.html</A><BR><BR><BR><A href="http://www.cnblogs.com/tintown/archive/2005/04/04/131784.html?Pending=true#PostPost">http://www.cnblogs.com/tintown/archive/2005/04/04/131784.html?Pending=true#PostPost</A><BR><BR><BR><A href="http://www.cnblogs.com/tintown/archive/2005/04/07/132876.html">http://www.cnblogs.com/tintown/archive/2005/04/07/132876.html</A><BR><BR><A href="http://blog.sunmast.com/sunmast/articles/816.aspx">http://blog.sunmast.com/sunmast/articles/816.aspx</A><BR><BR>ADO.NET对象模型：<BR><A href="http://www.phome.net/document/net/200504/net111246243813950.html">http://www.phome.net/document/net/200504/net111246243813950.html</A><BR><IMG height=418 src="http://www.phome.net/d/file/document/net/2005-04-02/0442c2b7c534a4e24d69d393bf36bcd5.jpg" width=436><BR><BR><A href="http://www.phome.net/document/net/200504/net111246243713949.html">http://www.phome.net/document/net/200504/net111246243713949.html</A><BR><IMG src="file:///C:/Documents%20and%20Settings/IJ1147/Local%20Settings/Temporary%20Internet%20Files/Content.IE5/GRTB66FP/7a1e5676cdeb55c0b2c250e6cda46d20%5B1%5D.jpg"><BR><BR><IMG height=253 src="http://www.phome.net/d/file/document/net/2005-04-02/bb4502f4244aea539a18c873c1b5366b.jpg" width=378><BR><IMG height=305 src="http://www.phome.net/d/file/document/net/2005-04-02/8137feebd8f8d86e60649e9aae46c7f0.jpg" width=483>&nbsp;<BR><BR><BR>
<DIV align=center><FONT size=3><STRONG>ADO.NET--什么是关系型数据库<BR></STRONG></FONT></DIV><BR><A href="http://www.phome.net/document/net/200504/net111246244913952.html">http://www.phome.net/document/net/200504/net111246244913952.html</A><BR><BR><BR><A href="http://blog.csdn.net/jabby12/archive/2004/08/02/59221.aspx">ADO.NET对象模型</A> <BR><A href="http://blog.csdn.net/jabby12/archive/2004/08/02/59221.aspx">http://blog.csdn.net/jabby12/archive/2004/08/02/59221.aspx</A><BR>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ADO.NET是专门为帮助开发人员开发高效的多层数据库应用程序设计的。ADO.NET对象模型可分为两类：一类为“连接的”，一类为“断开连接的”对象，后者允许将查询结果保存在内存中进行处理。</P>
<P>”连接的“对象模型顾名思义，它是直接与数据库进行连接操作;“断开连接”的对象模型可以说是建立在“连接的”对象模型的基础上进行的，因为它必须先进行一次“连接的”操作，才能得到所需的结果。</P>
<P>&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;</P>
<P>SqlConnection con=new SqlConnection("server=localhost;database=db,uid=sa,pwd=;");</P>
<P>SqlDataAdapter ad=new SqlDataAdapter("select * from table",con);</P>
<P>DataSet ds=new Dataset();</P>
<P>ad.Fill(ds,"table"); </P>
<P>//注意这里已经将从数据库里查询出来的结果放到一个Dataset对象里，从此刻开始，你就开始使用“断开连接”的对象模型来对数据库进行操作，DataSet对象是一个在内存中的”虚数据表“，你可以对它进行任何操作而不影响数据库，可以对它进行排序，修改，查询，增加，删除。而如果你想更改数据库内容的话，也可以通过DataSet对象来操作，很简单，调用它的update()方法即可完成更新数据库。也可以使用它的GetChanges()方法来获取只更改过的行，它返回一个DataSet，这个Dataset不同于调用GetChanges()方法的那个，返回的这个只是它的一张子表，也就是更改过的数据，利用此方法可以大大地提高多层ADO.NET应用程序的性能。DataSet类还有一个Merge方法用来合并两个DataSet对象的数据，ADO.NET默认覆盖被调用Merge()方法的DataSet中的行。</P>
<P>ADO.NET还提供了一种强类型的DATASET对象：它可以帮助你简化建立数据访问应用程序的过程。例如：有个表叫table,其中有一列叫column你可以这样来访问此列：</P>
<P>vb.net:&nbsp;&nbsp;&nbsp;&nbsp;Dim ds as DataSet </P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(ds.table(0).column);&nbsp;&nbsp;&nbsp;(table(0).表示table表中的第1行）</P>
<P>c#:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSet ds;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(ds.table[0].column);&nbsp; (table[0].表示table表中的第1行）</P>
<P>是不是很简洁: ^_^</P>
<P>关于DataSet里面还有好多东西方便用如：DataTable,DataView,DataRow,DataColumn,DataRelation,Constraint一大堆的好东西，在以后的日志中会提到！<BR></P><BR><BR>&nbsp;&nbsp;可见，在分层的时候，我们会增加一个实体层，它的作用如下： <BR>&nbsp;&nbsp;① 将显示数据和实际的存储区域隔离，保证了业务的独立性，提高了可重用性。 <BR>&nbsp;&nbsp;② 在业务层和表现层之间传递数据。（如果没有实体层的话，我们需要把表的每个字段作为一个参数在它们之间传递，如果修改的话，将需要影响到程序的各个层） <BR>&nbsp;&nbsp;③ 提供更大的可收缩性。 <BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;2） 业务实体层的几种选择方案及其优缺点。 <BR>&nbsp;&nbsp;在.NET环境下实现业务实体有下面的几种选择： <BR>&nbsp;&nbsp;① DataReader BE 具有最快的读取速度，用于只读的场合，不具有OO的概念。 <BR>&nbsp;&nbsp;② XML BE 可以与XML Reader和DataSet转换。缺点：性能低，验证、解析、显示、排序等都很复杂。 <BR>&nbsp;&nbsp;③ Generic DataSet BE 优点：数据绑定等。缺点：客户端必须通过集合来获取数据，没有类型，实例化开销大，调度性能低。 <BR>&nbsp;&nbsp;④ Typed DataSet BE 优点：由类型，可以进行类型检查。缺点：只能从DataSet继承，部署不方便，可扩展性差，实例化开销大，调度性能低。 <BR>&nbsp;&nbsp;⑤ Custom BE　优点：性能调优，代码更具有可读性，用自定义实体类定义一个良好的接口，将复杂问题隐藏在其中。缺点：设计开发都很复杂，需要自己去实现CURD操作，自己去实现数据绑定，工作量很大。 <BR>&nbsp;&nbsp;⑥ O/R Mapping的实现 它具有自定义类的所有优点，同时实现了CRUD，数据绑定等操作。 <BR><BR>关于ObjectSpaces 和<U><FONT color=#800080>llblgen </FONT></U><BR><A href="http://www.llblgen.com/defaultgeneric.aspx">http://www.llblgen.com/defaultgeneric.aspx</A><BR><A href="http://www.sinzy.net/blog/Read.asp?ID=44&amp;BID=931">http://www.sinzy.net/blog/Read.asp?ID=44&amp;BID=931</A><BR><BR><BR><A href="http://www.csdn.net/develop/author/NetAuthor/sun2bin/">http://www.csdn.net/develop/author/NetAuthor/sun2bin/</A><A href="http://www.cnblogs.com/william_fire/articles/126665.html"></A><img src ="http://www.blogjava.net/kapok/aggbug/3134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-13 13:40 <a href="http://www.blogjava.net/kapok/archive/2005/04/13/3134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Implementing Data Transfer Object in .NET with a Typed DataSet</title><link>http://www.blogjava.net/kapok/archive/2005/04/12/3173.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 12 Apr 2005 04:49:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/12/3173.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3173.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/12/3173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3173.html</trackback:ping><description><![CDATA[<H1 class=dtH1><A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/ImpDTOtypedDataSet.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/ImpDTOtypedDataSet.asp</A></H1>
<H1 class=dtH1><A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconworkingwithtypeddataset.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconworkingwithtypeddataset.asp</A></H1>
<H1 class=dtH1>Implementing Data Transfer Object in .NET with a Typed DataSet</H1>
<P>
<TABLE cellSpacing=0 cellPadding=0 bgColor=#eeeeee>
<TBODY>
<TR>
<TD><IMG height=26 alt=? src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_TL.gif" width=26 border=0></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Data Column: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_toptab_D1.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Application Column: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_toptab_A1-up.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Deployment Column: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_toptab_D1.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Infrastructure Column: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_toptab_I1.gif" width=45 border=0></A></TD></TR>
<TR>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Architecture Row: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_sidetab_A.gif" width=26 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Data Architecture: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_1.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Application Architecture: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_2.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Deployment Architecture: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_3.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Infrastructure Architecture: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_4.gif" width=45 border=0></A></TD></TR>
<TR>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/designpatoverview.aspx"><IMG height=26 alt="Design Row: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_sidetab_D.gif" width=26 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Data Design: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_5.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Application Design: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_6.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Deployment Design: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_7.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Infrastructure Design: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_8.gif" width=45 border=0></A></TD></TR>
<TR>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/implpatoverview.aspx"><IMG height=26 alt="Implementation Row" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_sidetab_I-up.gif" width=26 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Data Implementation: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_9.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Application Implementation: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_10-up.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Deployment Implementation: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_11.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MSpatterns.asp"><IMG height=26 alt="Infrastructure Implementation: select for more on pattern organization" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_12.gif" width=45 border=0></A></TD></TR>
<TR>
<TD><IMG height=27 alt=? src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_BL.gif" width=26 border=0></TD>
<TD><A href="http://msdn.microsoft.com/practices"><IMG height=27 alt="Complete List of patterns &amp; practices" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_logo1.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/practices"><IMG height=27 alt="Complete List of patterns &amp; practices" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_logo2.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/practices"><IMG height=27 alt="Complete List of patterns &amp; practices" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_logo3.gif" width=37 border=0></A></TD>
<TD><A href="http://msdn.microsoft.com/practices"><IMG height=27 alt="Complete List of patterns &amp; practices" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/MapNav_logo4.gif" width=45 border=0></A></TD></TR></TBODY></TABLE></P>
<P>Version 1.0.0</P>
<P><A href="http://www.gotdotnet.com/Community/Workspaces/workspace.aspx?id=0aac3f2c-53c1-45d1-b79d-81f7c9382cc7"><FONT color=gray>GotDotNet community for collaboration on this pattern</FONT></A></P>
<P><A href="http://msdn.microsoft.com/practices/"><FONT color=gray>Complete List of patterns &amp; practices</FONT></A></P>
<P></P>
<H2 class=dtH1>
<P>Context</P></H2>
<P>You are implementing a distributed application with the .NET Framework. The client application displays a form that requires making multiple calls to an ASP.NET Web service to satisfy a single user request. Based on performance measurements you have found that making multiple calls degrades application performance. To increase performance, you would like to retrieve all the data that the user request requires in a single call to the Web service. </P>
<H2 class=dtH1>
<P>Background </P></H2>
<BLOCKQUOTE class=dtBlock>
<P>
<P><B>Note:</B> The following is the same sample application that is described in <A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/ImpDTODataSet.asp"><I>Implementing Data Transfer Object in .NET with a DataSet</I></A>. </P>
<P></P>
<P>
<P>The following is a simplified Web application that communicates with an ASP.NET Web service to deliver recording and track information to the user. The Web service in turn calls a database to provide the data that the client requests. The following sequence diagram depicts the interaction among the application, the Web service, and the database for a typical page. </P>
<P></P></BLOCKQUOTE>
<P><IMG src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/Imp_DTO_with_DataSet_Fig01.gif"></P>
<P><HEAD3>Figure 1: Behavior of a typical user request</HEAD3></P>
<P>
<P>Figure 1 illustrates the sequence of calls needed to fulfill the entire user request. The first call retrieves the recording information, and the second call retrieves the track information for the specified recording. In addition, the Web service must make separate calls to the database to retrieve the required information. </P>
<P></P>
<H3 class=dtH1>
<P>Database Schema</P></H3>
<P></P>
<P>
<P>The schema that is used in the example shown in Figure 2 depicts a <B>recording</B> record that has a one-to-many relationship with a <B>track</B> record. </P>
<P></P>
<P><IMG src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/Imp_DTO_with_DataSet_Fig02.gif"></P>
<P><HEAD3>Figure 2: Schema for sample application</HEAD3></P>
<H3 class=dtH1>
<P>Implementing a DTO</P></H3>
<P></P>
<P>
<P>One way to improve the performance of this user request is to package all the required data into a data transfer object (DTO) that can be sent with a single call to the Web service. This reduces the overhead associated with two separate calls and allows you to use a single connection with the database to retrieve both the recording and the track information. For a detailed description of how this improves performance, see the <A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/DesDTO.asp"><I>Data Transfer Object</I></A> pattern. </P>
<P></P>
<H2 class=dtH1>
<P>Implementation Strategy</P></H2>
<P>A typed <B>DataSet</B> is a generated subclass of <B>System.Data.DataSet</B>. You provide an XML schema file which is then used to generate a strongly-typed wrapper around the <B>DataSet</B>. The following two code samples illustrate the differences. The first sample is implemented with an ordinary <B>DataSet</B>: </P><PRE class=code> 

DataTable dataTable = dataSet.Tables["recording"];
DataRow row = dataTable.Rows[0];
string artist = (string)row["artist"];
 </PRE>
<P>This sample indicates that you need to know the table and column names to access the tables and fields contained in the <B>DataSet</B>. You also have to know the return type of the Artist field to ensure that the correct cast is done. If you do not use the correct type, you will get a runtime error. The following is the same example implemented with a typed <B>DataSet</B>:</P><PRE class=code> 

   Recording recording = typedDataSet.Recordings[0];
   string artist = recording.Artist; 
 </PRE>
<P>This example demonstrates the benefits that the typed interface provides. You no longer have to refer to table or column by name and you do not have to know that the return type of the Artist column is a string. A typed <B>DataSet</B> defines a much more explicit interface that is verifiable at compile time instead of at runtime. In addition to the strongly-typed interface a typed <B>DataSet</B> also can be used in all places a <B>DataSet</B> can be used; therefore, it also can be used as a DTO. It is loaded in a similar fashion as a <B>DataSet</B> and it can be serialized to and from XML. In comparison to an ordinary <B>DataSet</B> you do have to write and maintain an XML schema that describes the typed interface. The Microsoft Visual Studio .NET development system provides a number of tools that simplify the creation and maintenance of the schema.The rest of this implementation strategy outlines the steps required in creating a typed <B>DataSet</B> for the sample application just described. </P>
<H3 class=dtH1>
<P>Creating a Typed DataSet</P></H3>
<P></P>
<P>
<P>A typed DataSet is generated from an XML schema. Visual Studio .NET provides a drag-and-drop tool which automates the creation of the schema (see Figure 3) and the generation of the typed DataSet classes. If you do not use Visual Studio.NET, you can write the XML schema and use a command-line tool called XSD.exe to generate the typed DataSet. For detailed instructions on both of these methods, see "Typed DataSets in ADO.NET" from the May 2001 issue of <I>.NET Developer</I> [Wildermuth02]. </P>
<P></P>
<P><IMG src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/Imp_DTO_with_Typed_DataSet_Fig03.gif"></P>
<P><HEAD3>Figure 3: Visual Studio .NET DataSet file type</HEAD3></P>
<H4 class=dtH1>
<P>RecordingDto.xsd</P></H4>
<P></P>
<P>
<P>The following is the XML schema for the DTO to be used in this example. It combines both the recording table along with its associated track records in a single typed DataSet named <B>RecordingDto</B>:</P>
<P></P><PRE class=code> 

&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;xs:schema id="RecordingDto" targetNamespace="http://msdn.microsoft.com/practices/RecordingDto.xsd"
   elementFormDefault="qualified" attributeFormDefault="qualified" xmlns="http://tempuri.org/RecordingDTO.xsd"
   xmlns:mstns="http://msdn.microsoft.com/practices/RecordingDto.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:codegen="urn:schemas-microsoft-com:xml-msprop"&gt;
   &lt;xs:element name="RecordingDto" msdata:IsDataSet="true"&gt;
      &lt;xs:complexType&gt;
         &lt;xs:choice maxOccurs="unbounded"&gt;
            &lt;xs:element name="recording" codegen:typedName="Recording" codegen:typedPlural="Recordings"
               codegen:typedChildren="Track"&gt;
               &lt;xs:complexType&gt;
                  &lt;xs:sequence&gt;
                     &lt;xs:element name="id" type="xs:long" codegen:typedName="Id" /&gt;
                     &lt;xs:element name="title" type="xs:string" codegen:typedName="Title" /&gt;
                     &lt;xs:element name="artist" type="xs:string" codegen:typedName="Artist" /&gt;
                  &lt;/xs:sequence&gt;
               &lt;/xs:complexType&gt;
            &lt;/xs:element&gt;
            &lt;xs:element name="track" codegen:typedName="Track" codegen:typedPlural="Tracks" codegen:typedParent="Recording"&gt;
               &lt;xs:complexType&gt;
                  &lt;xs:sequence&gt;
                     &lt;xs:element name="id" type="xs:long" codegen:typedName="Id" /&gt;
                     &lt;xs:element name="title" type="xs:string" codegen:typedName="Title" /&gt;
                     &lt;xs:element name="duration" type="xs:string" codegen:typedName="Duration" /&gt;
                     &lt;xs:element name="recordingId" type="xs:long" codegen:typedName="RecordingId" /&gt;
                  &lt;/xs:sequence&gt;
               &lt;/xs:complexType&gt;
            &lt;/xs:element&gt;
         &lt;/xs:choice&gt;
      &lt;/xs:complexType&gt;
      &lt;xs:unique name="RecordingDTOKey1" msdata:PrimaryKey="true"&gt;
         &lt;xs:selector xpath=".//mstns:recording" /&gt;
         &lt;xs:field xpath="mstns:id" /&gt;
      &lt;/xs:unique&gt;
      &lt;xs:unique name="RecordingDTOKey2" msdata:PrimaryKey="true"&gt;
         &lt;xs:selector xpath=".//mstns:track" /&gt;
         &lt;xs:field xpath="mstns:id" /&gt;
      &lt;/xs:unique&gt;
      &lt;xs:keyref name="recordingtrack" refer="mstns:RecordingDTOKey1"&gt;
         &lt;xs:selector xpath=".//mstns:track" /&gt;
         &lt;xs:field xpath="mstns:recordingId" /&gt;
      &lt;/xs:keyref&gt;
   &lt;/xs:element&gt;
&lt;/xs:schema&gt;
 </PRE>
<P>This schema is not the exact file produced by Visual Studio .NET. It is annotated with a number of attributes that are prefixed from the <B>codegen</B> namespace. This modification is desirable because the code that is generated does not adhere to the .NET naming conventions. For example, without the modification, Visual Studio .NET would generate a <B>track</B> class that corresponds to the track table, whereas according to conventions used in the .NET Framework the class should be named <B>Track</B>. To change the name of the class that is generated, you must add the codegen:typedName attribute to the element definition in the XML schema:</P><PRE class=code> 

&lt;xs:element name="track" codegen:typedName="Track"&gt;
   
&lt;/element&gt;
 </PRE>
<P>There are a number of other attributes besides codegen:typedName. For a detailed description of all the attributes, see "Typed DataSets in ADO.NET" from the May 2001 issue of <I>.NET Developer</I> [Wildermuth02].</P>
<H3 class=dtH1>
<P>Filling a Typed DataSet from the Database</P></H3>
<P></P>
<P>
<P>The following code example demonstrates how to fill a typed <B>DataSet</B> with the data that the sample application requires. This includes the specific <B>recording</B> record and all of its associated <B>track</B> records. The difference between this code and filling an ordinary <B>DataSet</B> is that you do not need to explicitly define the relationship between the recording and track records. </P>
<P></P>
<H4 class=dtH1>
<P>Assembler.cs</P></H4>
<P></P>
<P>
<P>Just as in <I>Implementing a Data Transfer Object in .NET with a DataSet</I>, an <B>Assembler</B> class maps the actual database calls into the typed <B>DataSet</B>: </P>
<P></P><PRE class=code> 

using System;
using System.Data;
using System.Data.SqlClient;

using Recording;

public class Assembler
{
   public static RecordingDto CreateRecordingDto(long id)
   {
      string selectCmd = 
         String.Format(
         "select * from recording where id = {0}",
         id);

      SqlConnection myConnection = 
         new SqlConnection(
         "server=(local);database=recordings;Trusted_Connection=yes;");
      SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, 
         myConnection);

      RecordingDto dto = new RecordingDto();
      myCommand.Fill(dto, "recording");

      String trackSelect = 
         String.Format(
         "select * from Track where recordingId = {0} order by Id",
         id);

      SqlDataAdapter trackCommand = 
         new SqlDataAdapter(trackSelect, myConnection);
      trackCommand.Fill(dto, "track");

      return dto;
   }
}
 </PRE>
<BLOCKQUOTE class=dtBlock>
<P>
<P><B>Note:</B> The example shown here is not meant to describe the only way to fill the typed <B>DataSet</B>. There are many ways to retrieve this data from the database. For example, you could use a stored procedure. </P>
<P></P></BLOCKQUOTE>
<H3 class=dtH1>
<P>Using a Typed DataSet in an ASP.NET Page</P></H3>
<P></P>
<P>
<P>As mentioned previously, a typed <B>DataSet</B> inherits from <B>System.Data.DataSet</B>. This means that it can be substituted for a <B>DataSet</B>. For example, when using the .NET user interface controls (Web Forms or Windows Forms) a typed <B>DataSet</B> can be used in all places you could use a <B>DataSet</B>. The sample application page shown in the following code example uses two <B>DataGrid</B> controls, <B>RecordingGrid</B> and <B>TrackGrid</B>. You can use the typed <B>DataSet</B>, <B>RecordingDto</B> when setting the <B>DataSource</B> properties on the controls because a typed <B>DataSet</B> inherits from <B>DataSet</B>. </P>
<P></P><PRE class=code> 

using System;
using System.Data;
using RecordingApplication.localhost;

public class RetrieveForm : System.Web.UI.Page
{
   private RecordingCatalog catalog = new RecordingCatalog();
 
   // 

   protected void Button1_Click(object sender, System.EventArgs e)
   {
      string stringId = TextBox1.Text;
      long id = Convert.ToInt64(stringId);

      RecordingDTO dto = catalog.Get(id);
      RecordingGrid.DataSource = dto.recording;
      RecordingGrid.DataBind();

      TrackGrid.DataSource = dto.track;
      TrackGrid.DataBind();
   }
}
 </PRE>
<H2 class=dtH1>
<P>Tests</P></H2>
<P>Because the typed <B>DataSet</B> is generated by tools in the .NET Framework, you do not need to write tests to verify that it functions correctly. In the following tests, you are testing that the <B>Assembler</B> class loaded the typed <B>DataSet</B> correctly. </P>
<H3 class=dtH1>
<P>AssemblerFixture.cs</P></H3>
<P></P><PRE class=code> 

using NUnit.Framework;
using System.Data;
using Recording;

[TestFixture]
public class AssemblerFixture
{
   private RecordingDto dto;
   private RecordingDto.Recording recording;
   private RecordingDto.Track[] tracks; 
   
   [SetUp]
   public void Init()
   {
      dto = Assembler.CreateRecordingDto(1234);
      recording = dto.Recordings[0];
      tracks = recording.GetTracks();
   }

   [Test]
   public void RecordingCount()
   {
      Assert.Equals(1, dto.Recordings.Rows.Count);
   }

   [Test]
   public void RecordingTitle()
   {
      Assert.Equals("Up", recording.Title.Trim());
   }


   [Test]
   public void RecordingChild()
   {
      Assert.Equals(10, tracks.Length);

      foreach(RecordingDto.Track track in tracks)
      {
         Assert.Equals(recording.Id, track.RecordingId);
      }
   }

   [Test]
   public void TrackParent()
   {
      RecordingDto.Track track = tracks[0];
      RecordingDto.Recording parent = track.Recording;
      Assert.Equals("Up", parent.Title.Trim());
   }

   [Test]
   public void TrackContent()
   {
      RecordingDto.Track track = tracks[0];
      Assert.Equals("Darkness", track.Title.Trim());
   }

   [Test]
   public void InvalidRecording()
   {
      RecordingDto dto = Assembler.CreateRecordingDto(-1);
      Assert.Equals(0, dto.Recordings.Rows.Count);
      Assert.Equals(0, dto.Tracks.Rows.Count);
   }
}
 </PRE>
<P>These tests describe how to access the individual elements of the <B>DataSet</B>. Because of the use of a typed <B>DataSet</B>, the test code does not require the actual column names and does not require the return type to be cast. Comparing these tests with the ones described in <I>Implementing Data Transfer Object in .NET with a DataSet</I> reveals the differences between using a strongly-typed interface and a generic interface. The strongly-typed interface is easier to use and understand. It also provides the added benefit of compile-time checking on return types. 
<H2 class=dtH1>
<P>Resulting Context</P></H2>
<P>Implementing DTO with a typed <B>DataSet</B> shares a number of the same benefits and liabilities as implementing DTO with a <B>DataSet</B>; however, certain benefits and liabilities are unique to a typed-<B>DataSet</B> implementation.</P>
<H3 class=dtH1>
<P>Benefits</P></H3>
<P></P>
<P>
<P>The typed <B>DataSet</B> shares the following benefits with a <B>DataSet</B> when used as a DTO: </P>
<P></P>
<LI>
<P><B>Development tool support</B>. Because the <B>DataSet</B> class is implemented in ADO.NET, there is no need to design and implement the DTO. There is also extensive support in Visual Studio for automating the creation and filling of <B>DataSet</B> and typed-<B>DataSet</B> objects. </P>
<LI>
<P><B>Integration with controls</B>. A <B>DataSet</B> works directly with the built-in controls in Windows Forms and Web Forms, making it a logical choice as a DTO. </P>
<LI>
<P><B>Serialization</B>. The <B>DataSet</B> comes complete with the ability to serialize itself into XML. Not only is the content serialized, but the schema for the content is also present in the serialization. </P>
<LI>
<P><B>Disconnected database model</B>. The <B>DataSet</B> represents a snapshot of the current contents of the database. This means that you can alter the contents of the <B>DataSet</B> and subsequently use the <B>DataSet</B> as the means to update the database. </P>
<LI>
<P>An additional benefit that might persuade you to use a typed <B>DataSet</B> as opposed to an ordinary <B>DataSet</B> is the strongly-typed interface of the typed <B>DataSet</B>. A typed <B>DataSet</B>, as described here, generates classes that can be used to access the contained data. The classes present an interface which defines how the class is to be used in a more explicit manner. This removes the need for casting which was present in the <B>DataSet</B> implementation. </P>
<H3 class=dtH1>
<P>Liabilities</P></H3>
<P></P>
<P>
<P>The typed <B>DataSet</B> shares the following liabilities with a <B>DataSet</B> when used in the context of a DTO: </P>
<P></P>
<LI>
<P><B>Interoperability</B>. Because the <B>DataSet</B> class is part of ADO.NET, it is not the best choice for a DTO in cases requiring interoperability with clients that are not running the .NET Framework.. You can still use <B>DataSet</B>, however, the client will be forced to parse the XML and build its own representation. If interoperability is a requirement, see <I>Implementing Data Transfer Object in .NET with Serialized Objects</I>. </P>
<LI>
<P><B>Stale data</B>. The typed <B>DataSet</B>, like a <B>DataSet</B>, is disconnected from the database. It is filled with a snapshot of the data in the database when it is constructed. This implies that the actual data in the database may be different from what is contained in the typed <B>DataSet</B>. For reading primarily static data, this is not a major issue. If the data is constantly changing, however, using any kind of <B>DataSet</B> is not recommended. </P>
<LI>
<P><B>Potential for performance degradation</B>. Instantiating and filling a <B>DataSet</B> can be an expensive operation. Serializing and deserializing a <B>DataSet</B> can also be very time consuming. A good rule of thumb for using a <B>DataSet</B> is that a <B>DataSet</B> is a good choice when you are using more than one table or relying on the capability of the <B>DataSet</B> to update the database. If you are displaying the results from a single table, then using a <B>DataReader</B> with strongly-typed objects may offer better performance. For more information, see <I>Implementing Data Transfer Object in .NET with Serialized Objects</I>. </P>
<LI>
<P>The following are additional liabilities when using a typed <B>DataSet</B> as opposed to an ordinary <B>DataSet</B>: </P>
<LI>
<P><B>A typed DataSet is still a DataSet. </B>A typed <B>DataSet</B> can be substituted at runtime with a <B>DataSet</B>. This means that even though the strongly-typed interface exists, programmers can still access the data without the typed interface. A possible result of doing this is that there could be parts of the code which couple the application tightly to the <B>DataSet</B> table and column names. </P>
<LI>
<P><B>The need for an XML schema</B>. When using a typed DataSet you have to create and maintain an XML schema to describe the strongly-typed interface. Visual Studio .NET provides a number of tools to assist in this process, but nevertheless you still have to maintain an additional file. </P>
<H2 class=dtH1>
<P>Related Patterns</P></H2>
<P>For more information, see the following related patterns:</P>
<LI>
<P><A href="http://msdn.microsoft.com/library/en-us/dnpatterns/html/ImpDTODataSet.asp"><I>Implementing Data Transfer Object in .NET with a DataSet</I></A>.</P>
<LI>
<P><I>Implementing Data Transfer Object in .NET with Serialized Objects</I>.</P>
<LI>
<P><I>Assembler</I>. In <I>Enterprise Application Architecture Patterns</I>, Fowler defines <I>Assembler</I> as a specialized instance of the <I>Mapper</I> pattern <I>[Fowler03].</I></P>
<H2 class=dtH1>
<P>Acknowledgments</P></H2>
<P>[Beau02] Beauchemin, Bob. <I>Essential ADO.NET</I>. Addison-Wesley, 2002.</P>
<P>[Fowler03] Fowler, Martin. <I>Enterprise Application Architecture Patterns</I>. Addison-Wesley, 2003.</P>
<P>[Wildermuth01] Wildermuth, Shawn. "Typed DataSets in ADO.NET." <I>.NET Developer</I>. May 2001.</P>
<P><IMG alt="Patterns Practices" src="http://msdn.microsoft.com/library/en-us/dnpatterns/html/PATTPRAC.gif"></P><!-- End Content --></LI><img src ="http://www.blogjava.net/kapok/aggbug/3173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-12 12:49 <a href="http://www.blogjava.net/kapok/archive/2005/04/12/3173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[zt]数据访问接口体系及数据对象模型探讨(Beat 1.0) .3</title><link>http://www.blogjava.net/kapok/archive/2005/04/12/3170.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 12 Apr 2005 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/12/3170.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3170.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/12/3170.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3170.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3170.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 数据访问接口体系及数据对象模型探讨(Beat 1.0) &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;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/kapok/archive/2005/04/12/3170.html'>阅读全文</a><img src ="http://www.blogjava.net/kapok/aggbug/3170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-12 10:34 <a href="http://www.blogjava.net/kapok/archive/2005/04/12/3170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ZT]数据访问接口体系及数据对象模型探讨(Beat 1.0) 2</title><link>http://www.blogjava.net/kapok/archive/2005/04/12/3169.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 12 Apr 2005 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/12/3169.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3169.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/12/3169.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3169.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3169.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://dev.csdn.net/develop/article/21/21019.shtm数据访问接口体系及数据对象模型探讨(Beat 1.0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&...&nbsp;&nbsp;<a href='http://www.blogjava.net/kapok/archive/2005/04/12/3169.html'>阅读全文</a><img src ="http://www.blogjava.net/kapok/aggbug/3169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-12 10:32 <a href="http://www.blogjava.net/kapok/archive/2005/04/12/3169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ZT]数据访问接口体系及数据对象模型探讨(Beat 1.0)</title><link>http://www.blogjava.net/kapok/archive/2005/04/12/3168.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Tue, 12 Apr 2005 02:31:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/12/3168.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3168.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/12/3168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3168.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://dev.csdn.net/develop/article/21/21018.shtm数据访问接口体系及数据对象模型探讨(Beat 1.0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/kapok/archive/2005/04/12/3168.html'>阅读全文</a><img src ="http://www.blogjava.net/kapok/aggbug/3168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-12 10:31 <a href="http://www.blogjava.net/kapok/archive/2005/04/12/3168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Just Google</title><link>http://www.blogjava.net/kapok/archive/2005/04/11/3129.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Mon, 11 Apr 2005 05:50:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/11/3129.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3129.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/11/3129.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3129.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3129.html</trackback:ping><description><![CDATA[<A href="http://www.blogjava.net/briansun/archive/2005/04/04/2808.html">http://www.blogjava.net/briansun/archive/2005/04/04/2808.html</A><BR><BR><A href="http://cj1215.blogchina.com/blog/article_23763.686125.html">http://cj1215.blogchina.com/blog/article_23763.686125.html</A><img src ="http://www.blogjava.net/kapok/aggbug/3129.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-11 13:50 <a href="http://www.blogjava.net/kapok/archive/2005/04/11/3129.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>娱乐场所 http://del.icio.us/</title><link>http://www.blogjava.net/kapok/archive/2005/04/11/3123.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Mon, 11 Apr 2005 04:37:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/04/11/3123.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/3123.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/04/11/3123.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/3123.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/3123.html</trackback:ping><description><![CDATA[<A href="http://del.icio.us/">http://del.icio.us/</A><BR><BR><A href="http://www.blogbus.com/blogbus/blog/diary.php?diaryid=319097">http://www.blogbus.com/blogbus/blog/diary.php?diaryid=319097</A><img src ="http://www.blogjava.net/kapok/aggbug/3123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-04-11 12:37 <a href="http://www.blogjava.net/kapok/archive/2005/04/11/3123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>reading trace</title><link>http://www.blogjava.net/kapok/archive/2005/03/28/2556.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Mon, 28 Mar 2005 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/03/28/2556.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/2556.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/03/28/2556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/2556.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/2556.html</trackback:ping><description><![CDATA[<A href="http://blog.csdn.net/javamxj/archive/2005/01/13/251861.aspx">http://blog.csdn.net/javamxj/archive/2005/01/13/251861.aspx</A><BR><BR><A href="http://blog.csdn.net/javamxj/archive/2005/01/13/251982.aspx">http://blog.csdn.net/javamxj/archive/2005/01/13/251982.aspx</A><BR><BR><A id=viewpost.ascx_TitleUrl href="http://blog.csdn.net/javamxj/archive/2005/01/11/248337.aspx">快速上手XDoclet 1 -- Servlet简单实例</A> <BR><A href="http://blog.csdn.net/javamxj/archive/2005/01/11/248337.aspx">http://blog.csdn.net/javamxj/archive/2005/01/11/248337.aspx</A><BR><BR><img src ="http://www.blogjava.net/kapok/aggbug/2556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-03-28 15:35 <a href="http://www.blogjava.net/kapok/archive/2005/03/28/2556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员与熬夜</title><link>http://www.blogjava.net/kapok/archive/2005/03/14/2071.html</link><dc:creator>笨笨</dc:creator><author>笨笨</author><pubDate>Mon, 14 Mar 2005 07:57:00 GMT</pubDate><guid>http://www.blogjava.net/kapok/archive/2005/03/14/2071.html</guid><wfw:comment>http://www.blogjava.net/kapok/comments/2071.html</wfw:comment><comments>http://www.blogjava.net/kapok/archive/2005/03/14/2071.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kapok/comments/commentRss/2071.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kapok/services/trackbacks/2071.html</trackback:ping><description><![CDATA[<A href="http://totodo.blogdriver.com/totodo/556180.html">http://totodo.blogdriver.com/totodo/556180.html</A><img src ="http://www.blogjava.net/kapok/aggbug/2071.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kapok/" target="_blank">笨笨</a> 2005-03-14 15:57 <a href="http://www.blogjava.net/kapok/archive/2005/03/14/2071.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>