<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>H31家园</title>
<link>http://h31home.com/</link>
<Description>欢迎光临使用H31家园</Description>
<language>zh-cn</language>
<copyright>Copyright 2006-2008 H31Home</copyright>
<webMaster>miao.whu@Gmail.com</webMaster>
<image>
	<title>H31家园</title> 
	<url>http://h31home.com/images/miao.gif</url> 
	<link>http://h31home.com/</link> 
	<description>欢迎光临使用H31家园</description> 
</image>
<item><link>http://h31home.com/h312005/blogview.asp?ID=998</link><title><![CDATA[分布式基础学习]]></title><author>admin</author><category>Linux学习</category><pubDate>2009-2-23 15:14:31</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=998</guid><description><![CDATA[http://www.cnblogs.com/duguguiyu/archive/2009/02/22/1396034.html

所谓分布式，在这里，很狭义的指代以Google的三驾马车，GFS、Map/Reduce、BigTable为框架核心的分布式存储和计算系统。通常如我一样初学的人，会以Google这几份经典的论文作为开端的。它们勾勒出了分布式存储和计算的一个基本蓝图，已可窥见其几分风韵，但终究还是由于缺少一些实现的代码和示例，色彩有些斑驳，缺少了点感性。幸好我们还有Open Source，还有Hadoop。Hadoop是一个基于Java实现的，开源的，分布式存储和计算的项目。作为这个领域最富盛名的开源项目之一，它的使用者也是大牌如云，包括了Yahoo，Amazon，Facebook等等（好吧，还可能有校内，不过这真的没啥分量...）。Hadoop本身，实现的是分布式的文件系统HDFS，和分布式的计算（Map/Reduce）框架，此外，它还不是一个人在战斗，Hadoop包含一系列扩展项目，包括了分布式文件数据库HBase（对应Google的BigTable），分布式协同服务ZooKeeper（对应Google的Chubby），等等。。。
如此，一个看上去不错的黄金搭档浮出水面，Google的论文 + Hadoop的实现，顺着论文的框架看具体的实现，用实现来进一步理解论文的逻辑，看上去至少很美。网上有很多前辈们，做过Hadoop相关的源码剖析工作，我关注最多的是这里，目前博主已经完成了HDFS的剖析工作，Map/Reduce的剖析正火热进行中，更新频率之高，剖析之详尽，都是难得一见的，所以，走过路过一定不要错过了。此外，还有很多Hadoop的关注者和使用者贴过相关的文章，比如：这里，这里。也可以去Hadoop的中文站点（不知是民间还是官方...），搜罗一些学习资料。。。
我个人从上述资料中受益匪浅，而我自己要做的整理，与原始的源码剖析有些不同，不是依照实现的模块，而是基于论文的脉络和实现这样系统的基本脉络来进行的，也算，从另一个角度给出一些东西吧。鉴于个人对于分布式系统的理解非常的浅薄，缺少足够的实践经验，深入的问题就不班门弄斧了，仅做梳理和解析，大牛至此，可绕路而行了。。。
一. 分布式文件系统

分布式文件系统，在整个分布式系统体系中处于最低层最基础的地位，存储嘛，没了数据，再好的计算平台，再完善的数据库系统，都成了无水之舟了。那么，什么是分布式文件系统，顾名思义，就是分布式+文件系统。它包含这两个方面的内涵，从文件系统的客户使用的角度来看，它就是一个标准的文件系统，提供了一系列API，由此进行文件或目录的创建、移动、删除，以及对文件的读写等操作。从内部实现来看，分布式的系统则不再和普通文件系统一样负责管理本地磁盘，它的文件内容和目录结构都不是存储在本地磁盘上，而是通过网络传输到远端系统上。并且，同一个文件存储不只是在一台机器上，而是在一簇机器上分布式存储，协同提供服务，正所谓分布式。。。
因此，考量一个分布式文件系统的实现，其实不妨可以从这两方面来分别剖析，而后合二为一。首先，看它如何去实现文件系统所需的基本增删改查的功能。然后，看它如何考虑分布式系统的特点，提供更好的容错性，负载平衡，等等之类的。这二者合二为一，就明白了一个分布式文件系统，整体的实现模式。。。
I. 术语对照
说任何东西，都需要统一一下语言先，不然明明说的一个意思，却容易被理解到另一个地方去。Hadoop的分布式文件系统HDFS，基本是按照Google论文中的GFS的架构来实现的。但是，HDFS为了彰显其不走寻常路的本性，其中的大量术语，都与GFS截然不同。明明都是一个枝上长的土豆，它偏偏就要叫山药蛋，弄得水火不容的，苦了我们看客。秉承老好人，谁也不得罪的方针，文中，既不采用GFS的叫法，也不采用Hadoop的称谓，而是另辟蹊径，自立门户，搞一套自己的中文翻译，为了避免不必要的痛楚，特此先来一帖术语对照表，要不懂查一查，包治百病。。。

文中所用翻译 HDFS中的术语 GFS中的术语 术语解释 
主控服务器 NameNode Master 整个文件系统的大脑，它提供整个文件系统的目录信息，并且管理各个数据服务器。 
数据服务器 DataNode Chunk Server 分布式文件系统中的每一个文件，都被切分成若干个数据块，每一个数据块都被存储在不同的服务器上，此服务器称之为数据服务器。 
数据块 Block Chunk 每个文件都会被切分成若干个块，每一块都有连续的一段文件内容，是存储的基恩单位，在这里统一称做数据块。 
数据包 Packet 无 客户端写文件的时候，不是一个字节一个字节写入文件系统的，而是累计到一定数量后，往文件系统中写入一次，每发送一次的数据，都称为一个数据包。 
传输块 Chunk 无 在每一个数据包中，都会将数据切成更小的块，每一个块配上一个奇偶校验码，这样的块，就是传输块。 
备份主控服务器 SecondaryNameNode 无 备用的主控服务器，在身后默默的拉取着主控服务器 的日志，等待主控服务器牺牲后被扶正。 


*注：本文采用的Hadoop是0.19.0版本。
II. 基本架构
1. 服务器介绍
与单机的文件系统不同，分布式文件系统不是将这些数据放在一块磁盘上，由上层操作系统来管理。而是存放在一个服务器集群上，由集群中的服务器，各尽其责，通力合作，提供整个文件系统的服务。其中重要的服务器包括：主控服务器（Master/NameNode），数据服务器（ChunkServer/DataNode），和客户服务器。HDFS和GFS都是按照这个架构模式搭建的。个人觉得，其中设计的最核心内容是：文件的目录结构独立存储在一个主控服务器上，而具体文件数据，拆分成若干块，冗余的存放在不同的数据服务器上。
存储目录结构的主控服务器，在GFS中称为Master，在HDFS中称为NameNode。这两个名字，叫得都有各自的理由，是瞎子摸象各表一面。Master是之于数据服务器来叫的，它做为数据服务器的领导同志存在，管理各个数据服务器，收集它们的信息，了解所有数据服务器的生存现状，然后给它们分配任务，指挥它们齐心协力为系统服务；而NameNode是针对客户端来叫的，对于客户端而言，主控服务器上放着所有的文件目录信息，要找一个文件，必须问问它，由此而的此名。。。
主控服务器在整个集群中，同时提供服务的只存在一个，如果它不幸牺牲的话，会有后备军立刻前赴后继的跟上，但，同一时刻，需要保持一山不容二虎的态势。这种设计策略，避免了多台服务器间即时同步数据的代价，而同时，它也使得主控服务器很可能成为整个架构的瓶颈所在。因此，尽量为主控服务器减负，不然它做太多的事情，就自然而然的晋升成了一个分布式文件系统的设计要求。。。
每一个文件的具体数据，被切分成若干个数据块，冗余的存放在数据服务器。通常的配置，每一个数据块的大小为64M，在三个数据服务器上冗余存放（这个64M，不是随便得来的，而是经过反复实践得到的。因为如果太大，容易造成热点的堆叠，大量的操作集中在一台数据服务器上，而如果太小的话，附加的控制信息传输成本，又太高了。因此没有比较特定的业务需求，可以考虑维持此配置...）。数据服务器是典型的四肢发达头脑简单的苦力，其主要的工作模式就是定期向主控服务器汇报其状况，然后等待并处理命令，更快更安全的存放好数据。。。
此外，整个分布式文件系统还有一个重要角色是客户端。它不和主控服务和数据服务一样，在一个独立的进程中提供服务，它只是以一个类库（包）的模式存在，为用户提供了文件读写、目录操作等APIs。当用户需要使用分布式文件系统进行文件读写的时候，把客户端相关包给配置上，就可以通过它来享受分布式文件系统提供的服务了。。。
2. 数据分布
一个文件系统中，最重要的数据，其实就是整个文件系统的目录结构和具体每个文件的数据。具体的文件数据被切分成数据块，存放在数据服务器上。每一个文件数据块，在数据服务器上都表征为出双入队的一对文件（这是普通的Linux文件），一个是数据文件，一个是附加信息的元文件，在这里，不妨把这对文件简称为数据块文件。数据块文件存放在数据目录下，它有一个名为current的根目录，然后里面有若干个数据块文件和从dir0-dir63的最多64个的子目录，子目录内部结构等同于current目录，依次类推（更详细的描述，参见这里）。个人觉得，这样的架构，有利于控制同一目录下文件的数量，加快检索速度。。。
这是磁盘上的物理结构，与之对应的，是内存中的数据结构，用以表征这样的磁盘结构，方便读写操作的进行。Block类用于表示数据块，而FSDataset类是数据服务器管理文件块的数据结构，其中，FSDataset.FSDir对应着数据块文件和目录，FSDataset.FSVolume对应着一个数据目录，FSDataset.FSVolumeSet是FSVolume的集合，每一个FSDataset有一个FSVolumeSet。多个数据目录，可以放在不同的磁盘上，这样有利于加快磁盘操作的速度。相关的类图，可以参看这里 。。。
此外，与FSVolume对应的，还有一个数据结构，就是DataStorage，它是Storage的子类，提供了升级、回滚等支持。但与FSVolume不一样，它不需要了解数据块文件的具体内容，它只知道有这么一堆文件放这里，会有不同版本的升级需求，它会处理怎么把它们升级回滚之类的业务（关于Storage，可以参见这里）。而FSVolume提供的接口，都基本上是和Block相关的。。。
相比数据服务器，主控服务器的数据量不大，但逻辑更为复杂。主控服务器主要有三类数据：文件系统的目录结构数据，各个文件的分块信息，数据块的位置信息（就数据块放置在哪些数据服务器上...）。在GFS和HDFS的架构中，只有文件的目录结构和分块信息才会被持久化到本地磁盘上，而数据块的位置信息则是通过动态汇总过来的，仅仅存活在内存数据结构中，机器挂了，就灰飞烟灭了。每一个数据服务器启动后，都会向主控服务器发送注册消息，将其上数据块的状况都告知于主控服务器。俗话说，简单就是美，根据DRY原则，保存的冗余信息越少，出现不一致的可能性越低，付出一点点时间的代价，换取了一大把逻辑上的简单性，绝对应该是一个包赚不赔的买卖。。。
在HDFS中，FSNamespacesystem类就负责保管文件系统的目录结构以及每个文件的分块状况的，其中，前者是由FSDirectory类来负责，后者是各个INodeFile本身维护。在INodeFile里面，有一个BlockInfo的数组，保存着与该文件相关的所有数据块信息，BlockInfo中包含了从数据块到数据服务器的映射，INodeFile只需要知道一个偏移量，就可以提供相关的数据块，和数据块存放的数据服务器信息。。。
3、服务器间协议
在Hadoop的实现中，部署了一套RPC机制，以此来实现各服务间的通信协议。在Hadoop中，每一对服务器间的通信协议，都定义成为一个接口。服务端的类实现该接口，并且建立RPC服务，监听相关的接口，在独立的线程处理RPC请求。客户端则可以实例化一个该接口的代理对象，调用该接口的相应方法，执行一次同步的通信，传入相应参数，接收相应的返回值。基于此RPC的通信模式，是一个消息拉取的流程，RPC服务器等待RPC客户端的调用，而不会先发制人主动把相关信息推送到RPC客户端去。。。
其实RPC的模式和原理，实在是没啥好说的，之所以说，是因为可以通过把握好这个，彻底理顺Hadoop各服务器间的通信模式。Hadoop会定义一些列的RPC接口，只需要看谁实现，谁调用，就可以知道谁和谁通信，都做些啥事情，图中服务器的基本架构、各服务所使用的协议、调用方向、以及协议中的基本内容。。。

III. 基本的文件操作

基本的文件操作，可以分成两类，一个是对文件目录结构的操作，比如文件和目录的创建、删除、移动、更名等等；另一个是对文件数据流的操作，包括读取和写入文件数据。当然，文件读和写，是有本质区别的，尤其是在数据冗余的情况下，因此，当成两类操作也不足为过。此外，要具体到读写的类别，也是可以再继续分类下去的。在GFS的论文中，对于分布式文件系统的读写场景有一个重要的假定（其实是从实际业务角度得来的...）：就是文件的读取是由大数据量的连续读取和小数据量的随机读取组成，文件的写入则基本上都是批量的追加写，和偶尔的插入写（GFS中还有大量的假设，它们构成了分布式文件系统架构设计的基石。每一个系统架构都是搭建在一定假设上的，这些假设有些来自于实际业务的状况，有些是因为天生的条件约束，不基于假设理解设计，肯定会有失偏颇...）。在GFS中，对文件的写入分成追加写和插入写都有所支持，但是，在HDFS中仅仅支持追加写，这大大降低了复杂性。关于HDFS与GFS的一些不同，可以参看这里。。。
1. 文件和目录的操作
文件目录的信息，全部囤积在主控服务器上，因此，所有对文件目录的操作，只会直接涉及到客户端和主控服务器。整个目录相关的操作流程基本都是这样的：客户端DFSClient调用ClientProtocol定义的相关函数，该操作通过RPC传送到其实现者主控服务器NameNode那里，NameNode做相关的处理后（很少...），调用FSNamesystem的相关函数。在FSNamesystem中，往往是做一些验证和租约操作，具体的目录结构操作交由FSDirectory的相应函数来操作。最后，依次返回，经由RPC传送回客户端。具体各操作涉及到的函数和具体步骤，参见下表：


相关操作 ClientProtocol / NameNode FSNamesystem FSDirectory 关键步骤 
创建文件 create startFile addFile 1. 检查是否有写权限；
2. 检查是否已经存在此文件，如果是覆写，则先进行删除操作；
3. 在指定路径下添加INodeFileUnderConstruction的文件实例；
4. 写日志；
5. 签订租约。 
创建目录 mkdirs mkdirs mkdirs 1. 检查指定目录是否是目录；
2. 检查是否有相关权限；
3. 在指定路径的INode下，添加子节点；
4. 写日志。 
改名操作 rename renameTo renameTo 1. 检查相关路径的权限；
2. 从老路径下移除，在新路径下添加；
3. 修改相关父路径的修改时间；
4. 写日志；
5. 将租约从老路径移动到新路径下。 
删除操作 delete delete delete 1. 如果不是递归删除，确认指定路径是否是空目录；
2. 检查相关权限；
3. 在目录结构上移除相关INode；
4. 修改父路径的修改时间；
5. 将相关的数据块，放入到废弃队列中去，等待处理；
6. 写日志；
7. 废弃相关路径的租约。 
设置权限 setPermission setPermission setPermission 1. 检查owner判断是否有操作权限；
2. 修改指定路径下INode的权限；
3. 写日志。 
设置用户 setOwner setOwner setOwner 1. 检查是否有操作权限；
2. 修改指定路径下INode的权限；
3. 写日志。 
设置时间 setTimes setTimes setTimes 1. 检查是否有写权限；
2. 修改指定路径INode的时间信息；
3. 写日志。 



从上表可以看到，其实有的操作本质上还是涉及到了数据服务器，比如文件创建和删除操作。但是，之前提到，主控服务器只于数据服务器是一个等待拉取的地位，它们不会主动联系数据服务器，将指令传输给它们，而是放到相应的数据结构中，等待数据服务器来取。这样的设计，可以减少通信的次数，加快操作的执行速度。。。
另，上述步骤中，有些日志和租约相关的操作，从概念上来说，和目录操作其实没有任何联系，但是，为了满足分布式系统的需求，这些操作是非常有必要的，在此，按下不表。。。
2、文件的读取
不论是文件读取，还是文件的写入，主控服务器扮演的都是中介的角色。客户端把自己的需求提交给主控服务器，主控服务器挑选合适的数据服务器，介绍给客户端，让客户端和数据服务器单聊，要读要写随你们便。这种策略类似于DMA，降低了主控服务器的负载，提高了效率。。。
因此，在文件读写操作中，最主要的通信，发生在客户端与数据服务器之间。它们之间跑的协议是ClientDatanodeProtocol。从这个协议中间，你无法看到和读写相关的接口，因为，在Hadoop中，读写操作是不走RPC机制的，而是另立门户，独立搭了一套通信框架。在数据服务器一端，DataNode类中有一个DataXceiverServer类的实例，它在一个单独的线程等待请求，一旦接到，就启动一个DataXceiver的线程，处理此次请求。一个请求一个线程，对于数据服务器来说，逻辑上很简单。当下，DataXceiver支持的请求类型有六种，具体的请求包和回复包格式，请参见这里，这里，这里。在Hadoop的实现中，并没有用类来封装这些请求，而是按流的次序写下来，这给代码阅读带来挺多的麻烦，也对代码的维护带来一定的困难，不知道是出于何种考虑。。。
相比于写，文件的读取实在是一个简单的过程。在客户端DFSClient中，有一个DFSClient.DFSInputStream类。当需要读取一个文件的时候，会生成一个DFSInputStream的实例。它会先调用ClientProtocol定义getBlockLocations接口，提供给NameNode文件路径、读取位置、读取长度信息，从中取得一个LocatedBlocks类的对象，这个对象包含一组LocatedBlock，那里面有所规定位置中包含的所有数据块信息，以及数据块对应的所有数据服务器的位置信息。当读取开始后，DFSInputStream会先尝试从某个数据块对应的一组数据服务器中选出一个，进行连接。这个选取算法，在当下的实现中，非常简单，就是选出第一个未挂的数据服务器，并没有加入客户端与数据服务器相对位置的考量。读取的请求，发送到数据服务器后，自然会有DataXceiver来处理，数据被一个包一个包发送回客户端，等到整个数据块的数据都被读取完了，就会断开此链接，尝试连接下一个数据块对应的数据服务器，整个流程，依次如此反复，直到所有想读的都读取完了为止。。。
3、文件的写入
文件读取是一个一对一的过程，一个客户端，只需要与一个数据服务器联系，就可以获得所需的内容。但是，写入操作，则是一个一对多的流程。一次写入，需要在所有存放相关数据块的数据服务器都保持同步的更新，有任何的差池，整个流程就告失败。。。
在分布式系统中，一旦涉及到写入操作，并发处理难免都会沦落成为一个变了相的串行操作。因为，如果不同的客户端如果是任意时序并发写入的话，整个写入的次序无法保证，可能你写半条记录我写半条记录，最后出来的结果乱七八糟不可估量。在HDFS中，并发写入的次序控制，是由主控服务器来把握的。当创建、续写一个文件的时候，该文件的节点类，由INodeFile升级成为INodeFileUnderConstruction，INodeFileUnderConstruction是INodeFile的子类，它起到一个锁的作用。如果当一个客户端想创建或续写的文件是INodeFileUnderConstruction，会引发异常，因为这说明这个此处有爷，请另寻高就，从而保持了并发写入的次序性。同时，INodeFileUnderConstruction有包含了此时正在操作它的客户端的信息以及最后一个数据块的数据服务器信息，当追加写的时候可以更快速的响应。。。
与读取类似，DFSClient也有一个DFSClient.DFSOutputStream类，写入开始，会创建此类的实例。DFSOutputStream会从NameNode上拿一个LocatedBlock，这里面有最后一个数据块的所有数据服务器的信息。这些数据服务器每一个都需要能够正常工作（对于读取，只要还有一个能工作的就可以实现...），它们会依照客户端的位置被排列成一个有着最近物理距离和最小的序列（物理距离，是根据机器的位置定下来的...），这个排序问题类似于著名旅行商问题，属于NP复杂度，但是由于服务器数量不多，所以用最粗暴的算法，也并不会看上去不美。。。
文件写入，就是在这一组数据服务器上构造成数据流的双向流水线。DFSOutputStream，会与序列的第一个数据服务器建立Socket连接，发送请求头，然后等待回应。DataNode同样是建立DataXceiver来处理写消息，DataXceiver会依照包中传过来的其他服务器的信息，建立与下一个服务器的连接，并生成类似的头，发送给它，并等待回包。此流程依次延续，直到最后一级，它发送回包，反向着逐级传递，再次回到客户端。如果一切顺利，那么此时，流水线建立成功，开始正式发送数据。数据是分成一个个数据包发送的，所有写入的内容，被缓存在客户端，当写满64K，会被封装成DFSOutputStream.Packet类实例，放入DFSOutputStream的dataQueue队列。DFSOutputStream.DataStreamer会时刻监听这个队列，一旦不为空，则开始发送，将位于dataQueue队首的包移动到ackQueue队列的队尾，表示已发送但尚未接受回复的包队列。同时启动ResponseProcessor线程监听回包，直到收到相应回包，才将发送包从ackQueue中移除，表示成功。每一个数据服务器的DataXceiver收到了数据包，一边写入到本地文件中去，一边转发给下一级的数据服务器，等待回包，同前面建立流水线的流程。。。
当一个数据块写满了之后，客户端需要向主控服务器申请追加新的数据块。这个会引起一次数据块的分配，成功后，会将新的数据服务器组返还给客户端。然后重新回到上述流程，继续前行。。。
关于写入的流程，还可以参见这里。此外，写入涉及到租约问题，后续会仔细的来说。。。
IV. 分布式支持

如果单机的文件系统是田里勤恳的放牛娃，那么分布式文件系统就是刀尖上讨饭吃的马贼了。在分布式环境中，有太多的意外，数据随时传输错误，服务器时刻准备牺牲，很多平常称为异常的现象，在这里都需要按照平常事来对待。因此，对于分布式文件系统而言，仅仅是满足了正常状况下文件系统各项服务还不够，还需要保证分布式各种意外场景下健康持续的服务，否则，将一无是处。。。
1、服务器的错误恢复
在分布式环境中，哪台服务器牺牲都是常见的事情，牺牲不可怕，可怕的是你都没有时刻准备好它们会牺牲。作为一个合格的分布式系统，HDFS当然时刻准备好了前赴后继奋勇向前。HDFS有三类服务器，每一类服务器出错了，都有相应的应急策略。。。
a. 客户端

生命最轻如鸿毛的童鞋，应该就是客户端了。毕竟，做为一个文件系统的使用者，在整个文件系统中的地位，难免有些归于三流。而作为客户端，大部分时候，牺牲了就牺牲了，没人哀悼，无人同情，只有在在辛勤写入的时候，不幸辞世（机器挂了，或者网络断了，诸如此类...），才会引起些恐慌。因为，此时此刻，在主控服务器上对应的文件，正作为INodeFileUnderConstruction活着，仅仅为占有它的那个客户端服务者，做为一个专一的文件，它不允许别的客户端染指。这样的话，一旦占有它的客户端服务者牺牲了，此客户端会依然占着茅坑不拉屎，让如花似玉INodeFileUnderConstruction孤孤单单守寡终身。这种事情当然无法容忍，因此，必须有办法解决这个问题，办法就是：租约。。。
租约，顾名思义，就是当客户端需要占用某文件的时候，与主控服务器签订的一个短期合同。这个合同有一个期限，在这个期限内，客户端可以延长合同期限，一旦超过期限，主控服务器会强行终止此租约，将这个文件的享用权，分配给他人。。。
在打开或创建一个文件，准备追加写之前，会调用LeaseManager的addLease方法，在指定的路径下与此客户端签订一份租约。客户端会启动DFSClient.LeaseChecker线程，定时轮询调用ClientProtocol的renewLease方法，续签租约。在主控服务器一端，有一个LeaseManager.Monitor线程，始终在轮询检查所有租约，查看是否有到期未续的租约。如果一切正常，该客户端完成写操作，会关闭文件，停止租约，一旦有所意外，比如文件被删除了，客户端牺牲了，主控服务器都会剥夺此租约，如此，来避免由于客户端停机带来的资源被长期霸占的问题。。。
b. 数据服务器

当然，会挂的不只是客户端，海量的数据服务器是一个更不稳定的因素。一旦某数据服务器牺牲了，并且主控服务器被蒙在鼓中，主控服务器就会变相的欺骗客户端，给它们无法连接的读写服务器列表，导致它们处处碰壁无法工作。因此，为了整个系统的稳定，数据服务器必须时刻向主控服务器汇报，保持主控服务器对其的完全了解，这个机制，就是心跳消息。在HDFS中，主控服务器NameNode实现了DatanodeProtocol接口，数据服务器DataNode会在主循环中，不停的调用该协议中的sendHeartbeat方法，向NameNode汇报状况。在此调用中，DataNode会将其整体运行状况告知NameNode，比如：有多少可用空间、用了多大的空间，等等之类。NameNode会记住此DataNode的运行状况，作为新的数据块分配或是负载均衡的依据。当NameNode处理完成此消息后，会将相关的指令封装成一个DatanodeCommand对象，交还给DataNode，告诉数据服务器什么数据块要删除什么数据块要新增等等之类，数据服务器以此为自己的行动依据。。。
但是，sendHeartbeat并没有提供本地的数据块信息给NameNode，那么主控服务器就无法知道此数据服务器应该分配什么数据块应该删除什么数据块，那么它是如何决定的呢？答案就是DatanodeProtocol定义的另一个方法，blockReport。DataNode也是在主循环中定时调用此方法，只是，其周期通常比调用sendHeartbeat的更长。它会提交本地的所有数据块状况给NameNode，NameNode会和本地保存的数据块信息比较，决定什么该删除什么该新增，并将相关结果缓存在本地对应的数据结构中，等待此服务器再发送sendHeartbeat消息过来的时候，依照这些数据结构中的内容，做出相应的DatanodeCommand指令。blockReport方法同样也会返回一个DatanodeCommand给DataNode，但通常，只是为空（只有出错的时候不为空），我想，增加缓存，也许是为了确保每个指令都可以重复发送并确定被执行。。。
c. 主控服务器

当然，作为整个系统的核心和单点，含辛茹苦的主控服务器含泪西去，整个分布式文件服务集群将彻底瘫痪罢工。如何在主控服务器牺牲后，提拔新的主控服务器并迅速使其进入工作角色，就成了系统必须考虑的问题。解决策略就是：日志。。。
其实这并不是啥新鲜东西，一看就知道是从数据库那儿偷师而来的。在主控服务器上，所有对文件目录操作的关键步骤（具体文件内容所处的数据服务器，是不会被写入日志的，因为这些内容是动态建立的...），都会被写入日志。另外，主控服务器会在某些时刻，将当下的文件目录完整的序列化到本地，这称为镜像。一旦存有镜像，镜像前期所写的日志和其他镜像，都纯属冗余，其历史使命已经完成，可以报废删除了。在主控服务器不幸牺牲，或者是战略性的停机修整结束，并重新启动后，主控服务器会根据最近的镜像 + 镜像之后的所有日志，重建整个文件目录，迅速将服务能力恢复到牺牲前的水准。。。
对于数据服务器而言，它们会通过一些手段，迅速得知顶头上司的更迭消息。它们会立刻转投新东家的名下，在新东家旗下注册，并开始向其发送心跳消息，这个机制，可能用分布式协同服务来实现，这里不说也罢。。。
在HDFS的实现中，FSEditLog类是整个日志体系的核心，提供了一大堆方便的日志写入API，以及日志的恢复存储等功能。目前，它支持若干种日志类型，都冠以OP_XXX，并提供相关API，具体可以参见这里。为了保证日志的安全性，FSEditLog提供了EditLogFileOutputStream类作为写入的承载类，它会同时开若干个本地文件，然后依次写入，防止日志的损坏导致不可估量的后果。在FSEditLog上面，有一个FSImage类，存储文件镜像并调用FSEditLog对外提供相关的日志功能。FSImage是Storage类的子类，如果对数据块的讲述有所印象的话，你可以回忆起来，凡事从此类派生出来的东西，都具有版本性质，可以进行升级和回滚等等，以此，来实现产生镜像是对原有日志和镜像处理的复杂逻辑。。。
目前，在HDFS的日志系统中，有些地方与GFS的描述有所不同。在HDFS中，所有日志文件和镜像文件都是本地文件，这就相当于，把日志放在自家的保险箱中，一旦主控服务器挂了，别的后继而上的服务器也无法拿到这些日志和镜像，用于重振雄风。因此，在HDFS中，运行着一个SecondaryNameNode服务器，它做为主控服务器的替补，隐忍厚积薄发为篡位做好准备，其中，核心内容就是：定期下载并处理日志和镜像。SecondaryNameNode看上去像客户端一样，与NameNode之间，走着NamenodeProtocol协议。它会不停的查看主控服务器上面累计日志的大小，当达到阈值后，调用doCheckpoint函数，此函数的主要步骤包括：
首先是调用startCheckpoint做一些本地的初始化工作；

然后调用rollEditLog，将NameNode上此时操作的日志文件从edit切到edit.new上来，这个操作瞬间完成，上层写日志的函数完全感觉不到差别；

接着，调用downloadCheckpointFiles，将主控服务器上的镜像文件和日志文件都下载到此候补主控服务器上来；

并调用doMerge，打开镜像和日志，将日志生成新的镜像，保存覆盖；

下一步，调用putFSImage把新的镜像上传回NameNode；

再调用rollFsImage，将镜像换成新的，在日志从edit.new改名为edit；

最后，调用endCheckpoint做收尾工作。

整个算法涉及到NameNode和SecondaryNameNode两个服务器，最终结果是NameNode和SecondaryNameNode都依照算法进行前的日志生成了镜像。而两个服务器上日志文件的内容，前者是整个算法进行期间所写的日志，后者始终不会有任何日志。当主控服务器牺牲的时候，运行SecondaryNameNode的服务器立刻被扶正，在其上启动主控服务，利用其日志和镜像，恢复文件目录，并逐步接受各数据服务器的注册，最终向外提供稳定的文件服务。。。
同样的事情，GFS采用的可能是另外一个策略，就是在写日志的时候，并不局限在本地，而是同时书写网络日志，即在若干个远程服务器上生成同样的日志。然后，在某些时机，主控服务器自己，生成镜像，降低日志规模。当主控服务器牺牲，可以在拥有网络日志的服务器上启动主控服务，升级成为主控服务器。。。
GFS与HDFS的策略相比较，前者是化整为零，后者则是批量处理，通常我们认为，批量处理的平均效率更高一些，且相对而言，可能实现起来容易一些，但是，由于有间歇期，会导致日志的丢失，从而无法100%的将备份主控服务器的状态与主控服务器完全同步。。。
2、数据的正确性保证

在复杂纷繁的分布式环境中，我们坚定的相信，万事皆有可能。哪怕各个服务器都舒舒服服的活着，也可能有各种各样的情况导致网络传输中的数据丢失或者错误。并且在分布式文件系统中，同一份文件的数据，是存在大量冗余备份的，系统必须要维护所有的数据块内容完全同步，否则，一人一言，不同客户端读同一个文件读出不同数据，用户非得疯了不可。。。
在HDFS中，为了保证数据的正确性和同一份数据的一致性，做了大量的工作。首先，每一个数据块，都有一个版本标识，在Block类中，用一个长整型的数generationStamp来表示版本信息（Block类是所有表示数据块的数据结构的基类），一旦数据块上的数据有所变化，此版本号将向前增加。在主控服务器上，保存有此时每个数据块的版本，一旦出现数据服务器上相关数据块版本与其不一致，将会触发相关的恢复流程。这样的机制保证了各个数据服务器器上的数据块，在基本大方向上都是一致的。但是，由于网络的复杂性，简单的版本信息无法保证具体内容的一致性（因为此版本信息与内容无关，可能会出现版本相同，但内容不同的状况）。因此，为了保证数据内容上的一致，必须要依照内容，作出签名。。。
当客户端向数据服务器追加写入数据包时，每一个数据包的数据，都会切分成512字节大小的段，作为签名验证的基本单位，在HDFS中，把这个数据段称为Chunk，即传输块（注意，在GFS中，Chunk表达的是数据块...）。在每一个数据包中，都包含若干个传输块以及每一个传输块的签名，当下，这个签名是根据Java SDK提供的CRC算法算得的，其实就是一个奇偶校验。当数据包传输到流水线的最后一级，数据服务器会对其进行验证（想一想，为什么只在最后一级做验证，而不是每级都做...），一旦发现当前的传输块签名与在客户端中的签名不一致，整个数据包的写入被视为无效，Lease Recover（租约恢复）算法被触发。。。
从基本原理上看，这个算法很简单，就是取所有数据服务器上此数据块的最小长度当作正确内容的长度，将其他数据服务器上此数据块超出此长度的部分切除。从正确性上看，此算法无疑是正确的，因为至少有一个数据服务器会发现此错误，并拒绝写入，那么，如果写入了的，都是正确的；从效率上看，此算法也是高效的，因为它避免了重复的传输和复杂的验证，仅仅是各自删除尾部的一些内容即可。但从具体实现上来看，此算法稍微有些绕，因为，为了降低本已不堪重负的主控服务器的负担，此算法不是由主控服务器这个大脑发起的，而是通过选举一个数据服务器作为Primary，由Primary发起，通过调用与其他各数据服务器间的InterDatanodeProtocol协议，最终完成的。具体的算法流程，参见LeaseManager类上面的注释。需要说明的是此算法的触发时机和发起者。此算法可以由客户端或者是主控服务器发起，当客户端在写入一个数据包失败后，会发起租约恢复。因为，一次写入失败，不论是何种原因，很有可能就会导致流水线上有的服务器写了，有的没写，从而造成不统一。而主控服务器发起的时机，则是在占有租约的客户端超出一定时限没有续签，这说明客户端可能挂了，在临死前可能干过不利于数据块统一的事情，作为监督者，主控服务器需要发起一场恢复运动，确保一切正确。。。
3、负载均衡

负载的均衡，是分布式系统中一个永恒的话题，要让大家各尽其力齐心干活，发挥各自独特的优势，不能忙得忙死闲得闲死，影响战斗力。而且，负载均衡也是一个复杂的问题，什么是均衡，是一个很模糊的概念。比如，在分布式文件系统中，总共三百个数据块，平均分配到十个数据服务器上，就算均衡了么？其实不一定，因为每一个数据块需要若干个备份，各个备份的分布应该充分考虑到机架的位置，同一个机架的服务器间通信速度更快，而分布在不同机架则更具有安全性，不会在一棵树上吊死。。。
在这里说的负载均衡，是宽泛意义上的均衡过程，主要涵盖两个阶段的事务，一个是在任务初始分配的时候尽可能合理分配，另一个是在事后时刻监督及时调整。。。
在HDFS中，ReplicationTargetChooser类，是负责实现为新分配的数据块寻找婆家的。基本上来说，数据块的分配工作和备份的数量、申请的客户端地址（也就是写入者）、已注册的数据服务器位置，密切相关。其算法基本思路是只考量静态位置信息，优先照顾写入者的速度，让多份备份分配到不同的机架去。具体算法，自行参见源码。此外，HDFS的Balancer类，是为了实现动态的负载调整而存在的。Balancer类派生于Tool类，这说明，它是以一个独立的进程存在的，可以独立的运行和配置。它运行有NamenodeProtocol和ClientProtocol两个协议，与主控服务器进行通信，获取各个数据服务器的负载状况，从而进行调整。主要的调整其实就是一个操作，将一个数据块从一个服务器搬迁到另一个服务器上。Balancer会向相关的目标数据服务器发出一个DataTransferProtocol.OP_REPLACE_BLOCK消息，接收到这个消息的数据服务器，会将数据块写入本地，成功后，通知主控服务器，删除早先的那个数据服务器上的同一块数据块。具体的算法请自行参考源码。。。
4、垃圾回收
对于垃圾，大家应该耳熟能详了，在分布式文件系统而言，没有利用价值的数据块备份，就是垃圾。在现实生活中，我们提倡垃圾分类，为了更好的理解分布式文件系统的垃圾收集，搞个分类也是很有必要的。基本上，所有的垃圾都可以视为两类，一类是由系统正常逻辑产生的，比如某个文件被删除了，所有相关的数据块都沦为垃圾了，某个数据块被负载均衡器移动了，原始数据块也不幸成了垃圾了。此类垃圾最大的特点，就是主控服务器是生成垃圾的罪魁祸首，也就是说主控服务器完全了解有哪些垃圾需要处理。另外还有一类垃圾，是由于系统的一些异常症状产生的，比如某个数据服务器停机了一段，重启之后发现其上的某个数据块已经在其他服务器上重新增加了此数据块的备份，它上面的那个备份过期了失去价值了，需要被当作垃圾来处理了。此类垃圾的特点恰恰相反，主控服务器无法直接了解到垃圾状况，需要曲线救国。。。
在HDFS中，第一类垃圾的判定自然很容易，在一些正常的逻辑中产生的垃圾，全部被塞进了FSNamesystem的recentInvalidateSets这个Map中。而第二类垃圾的判定，则放在数据服务器发送其数据块信息来的过程中，经过与本地信息的比较，可以断定，此数据服务器上有哪些数据块已经不幸沦为垃圾。同样，这些垃圾也被塞到recentInvalidateSets中去。在与数据服务器进行心跳交流的过程中，主控服务器会将它上面有哪些数据块需要删除，数据服务器对这些数据块的态度是，直接物理删除。在GFS的论文中，对如何删除一个数据块有着不同的理解，它觉着应该先缓存起来，过几天没人想恢复它了再删除。在HDFS的文档中，则明确表示，在现行的应用场景中，没有需要这个需求的地方，因此，直接删除就完了。这说明，理念是一切分歧的根本：）。。。
V. 总结

整个分布式文件系统，计算系统，数据库系统的设计理念，基本是一脉相承的。三类服务器、作为单点存在的核心控制服务器、基于日志的恢复机制、基于租约的保持联系机制、等等，在后续分布式计算系统和分布式数据库中都可以看到类似的影子，在分布式文件系统这里，我详述了这些内容，可能在后续就会默认知道而说的比较简略了。而刨去这一些，分布式文件系统中最大特点，就是文件块的冗余存储，它直接导致了较为复杂的写入流程。当然，虽说分布式文件系统在分布式计算和数据库中都有用到，但如果对其机理没有兴趣，只要把它当成是一个可以在任何机器上使用的文件系统，就不会对其他上层建筑的理解产生障碍。。。]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=997</link><title><![CDATA[VC进程间通信消息]]></title><author>admin</author><category>VC学习</category><pubDate>2009-2-3 17:13:07</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=997</guid><description><![CDATA[进程间通信
void CH31Connect1Dlg::OnOK() 
{
CWnd *pCwnd； 
//用FindWindow函数找到想要关闭的应用程序的句柄的指针 
pCwnd=FindWindow(NULL,"H31CONNECT2")； 
//如果返回成功 
CString str="sendisok"；
COPYDATASTRUCT aa；
aa.dwData=1；
aa.cbData=str.GetLength()+1；
//memcpy(aa.lpData,str,aa.cbData)；
aa.lpData = (void*)str.GetBuffer(aa.cbData)；
if( pCwnd )
::SendMessage(pCwnd->m_hWnd,WM_COPYDATA,(WPARAM)this->m_hWnd,(LPARAM)&aa)；//给其发送关闭的消息 
}
程序2添加OnCopyData事件
BOOL CH31Connect2Dlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 
{
// TODO: Add your message handler code here and/or call default
CString aa = (LPCSTR)(pCopyDataStruct->lpData)； 
AfxMessageBox(aa)；
//return CDialog::OnCopyData(pWnd, pCopyDataStruct)；
return true；
}]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=996</link><title><![CDATA[C#测试委托+观察者模式]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-12-5 11:22:43</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=996</guid><description><![CDATA[using System；
using System.Collections.Generic；
using System.Text；
namespace ConsoleApplication1
{
      class Program
    {
        
        static void Main(string[] args)
        {
    //测试委托+观察者模式
            HBoss aa = new HBoss()；
            HObserver bb = new HObserver("XXXX", aa)；
            aa.Update += new EventHandler(bb.CloseStock)；
            aa.SubjectState = "Boss comeback.."；
            aa.Notify()；
        }
    }
    interface Subject
    {
        void Notify()；
        string SubjectState
        {
            get；
            set；
        }
    }
    class HObserver
    {
        private string name；
        private Subject sub；
        public HObserver(string name,Subject sub)
        {
            this.name = name；
            this.sub = sub；
        }
        public void CloseStock()
        {
            Console.WriteLine("{0},{1}关闭股票行情，继续工作", sub.SubjectState,name)；
        }
    }
    delegate void EventHandler()；
    class HBoss:Subject
    {
        public event EventHandler Update；
        private string action；
        public void Notify()
        {
            Update()；
        }
        public string SubjectState
        {
            get { return action； }
            set { action = value； }
        }
    }；
}
--------------------------------------------
using System；
using System.Collections.Generic；
using System.Text；
namespace ConsoleApplication1
{
     public class A   
    {   
        public A()   
        {   
        Console.WriteLine('A')；   
        }   
        public virtual void Fun()   
        {   
        Console.WriteLine("A.Fun()")；   
        }   
    }
    public class B : A
    {
        public B()
        {
            Console.WriteLine('B')；
        }
        public new void Fun()
        {
            Console.WriteLine("B.Fun()")；
        }
    }
    class Class1 
    { 
        public static int Count = 0； 
        static Class1() 
        { 
        Count++； 
        } 
        public Class1() 
        { 
        Count++； 
        } 
    } 
    class Program
    {
        
        static void Main(string[] args)
        {
            //A a = new B()；   
            //a.Fun()；
            //Class1 o1 = new Class1()；
            //Class1 o2 = new Class1()； 
   //输出A         B           A.Fun()

        }
    }
 
}]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=995</link><title><![CDATA[DataTable使用技巧总结 ]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-9-25 9:32:23</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=995</guid><description><![CDATA[       在项目中经常用到DataTable,如果DataTable使用得当，不仅能使程序简洁实用，而且能够提高性能，达到事半功倍的效果，现对DataTable的使用技巧进行一下总结。 


        一、DataTable简介     

          (1)构造函数 
          DataTable()   不带参数初始化DataTable 类的新实例。 
          DataTable(string tableName)  用指定的表名初始化DataTable 类的新实例。 
          DataTable(string tableName, string tableNamespace) 用指定的表名和命名空间初始化DataTable 类的新实例。 
          (2) 常用属性 
          CaseSensitive    指示表中的字符串比较是否区分大小写。 
          ChildRelations   获取此DataTable 的子关系的集合。 
          Columns             获取属于该表的列的集合。 
          Constraints        获取由该表维护的约束的集合。 
          DataSet               获取此表所属的DataSet。DataSet相关信息，可见我以前的一篇文章《数据访问(2)－DataSet》 
          DefaultView       获取可能包括筛选视图或游标位置的表的自定义视图。 
          HasErrors          获取一个值，该值指示该表所属的DataSet 的任何表的任何行中是否有错误。 
          MinimumCapacity  获取或设置该表最初的起始大小。该表中行的最初起始大小。默认值为 50。 
          Rows                  获取属于该表的行的集合。 
          TableName       获取或设置DataTable 的名称。 


          (3)常用方法 
          AcceptChanges()   提交自上次调用AcceptChanges() 以来对该表进行的所有更改。 
          BeginInit()         开始初始化在窗体上使用或由另一个组件使用的DataTable。初始化发生在运行时。 

          Clear()               清除所有数据的DataTable。 
          Clone()              克隆DataTable 的结构，包括所有DataTable 架构和约束。 
          EndInit()            结束在窗体上使用或由另一个组件使用的DataTable 的初始化。初始化发生在运行时。 
          ImportRow(DataRow row)    将DataRow 复制到DataTable 中，保留任何属性设置以及初始值和当前值。 
          Merge(DataTable table)  将指定的DataTable 与当前的DataTable 合并。 
          NewRow()         创建与该表具有相同架构的新DataRow。
 
        二、DataTable使用技巧

      （1）Create a DataTable
         DataTable dt = new DataTable("Table_AX")； 


      （2）Add columns for DataTable
        //Method 1
        dt.Columns.Add("column0", System.Type.GetType("System.String"))；
        //Method 2
        DataColumn dc = new DataColumn("column1", System.Type.GetType("System.Boolean"))；
        dt.Columns.Add(dc)； 

       （3）Add rows for DataTable
         //Initialize the row
         DataRow dr = dt.NewRow()；
         dr["column0"] = "AX"；
         dr["column1"] = true；
         dt.Rows.Add(dr)；
         //Doesn't initialize the row
         DataRow dr1 = dt.NewRow()；
         dt.Rows.Add(dr1)；  


        （4）Ｓelect row
         //Search the second row 如果没有赋值,则用is null来Ｓelect
         DataRow[] drs = dt.Ｓelect("column1 is null")；
         DataRow[] drss = dt.Ｓelect("column0 = 'AX'")； 


        （5）Copy DataTable include data
         DataTable dtNew = dt.Copy()； 

        （6）Copy DataTable only scheme
         DataTable dtOnlyScheme = dt.Clone()； 

        （7）Operate one row
         //对dt的操作
         //Method 1
         DataRow drOperate = dt.Rows[0]；
         drOperate["column0"] = "AXzhz"；
         drOperate["column1"] = false；
         //Method 2
         drOperate[0] = "AXzhz"；
         drOperate[1] = false；
         //Method 3
         dt.Rows[0]["column0"] = "AXzhz"；
         dt.Rows[0]["column1"] = false；
         //Method 4
         dt.Rows[0][0] = "AXzhz"；
         dt.Rows[0][1] = false； 

       （8）Evaluate another DataTable's row to current Datatable
         dtOnlyScheme.Rows.Add(dt.Rows[0].ItemArray)； 

       （9）Convert to string
         System.IO.StringWriter sw = new System.IO.StringWriter()；
         System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw)；
         dt.WriteXml(xw)；
         string s = sw.ToString()；

        （10）Filter DataTable
         dt.DefaultView.RowFilter = "column1 <> true"；
         dt.DefaultView.RowFilter = "column1 = true"；

        （11）Sort row
          dt.DefaultView.Sort = "ID ,Name ASC"；
          dt=dt.DefaultView.ToTable()；

         （12）Bind DataTable
           //绑定的其实是DefaultView
          gvTestDataTable.DataSource = dt；
          gvTestDataTable.DataBind()；

         （13）judge the DataTable’s Column name is a string
          //判断一个字符串是否为DataTable的列名
         dtInfo.Columns.Contains("AX")；

         （14）DataTable convert to XML and XML convert to DataTable
          protected void Page_Load(object sender, EventArgs e)
          {
             DataTable dt_AX = new DataTable()； 
             //dt_AX.Columns.Add("Sex", typeof(System.Boolean))；
             //DataRow dr = dt_AX.NewRow()；
             //dr["Sex"] = true；
             //dt_AX.Rows.Add(dr)； 
             string xml=ConvertBetweenDataTableAndXML_AX(dt_AX)；
             DataTable dt = ConvertBetweenDataTableAndXML_AX(xml)；
         } 
         public string ConvertBetweenDataTableAndXML_AX(DataTable dtNeedCoveret)
        {
             System.IO.TextWriter tw = new System.IO.StringWriter()；
             //if TableName is empty, WriteXml() will throw Exception.                  

dtNeedCoveret.TableName=dtNeedCoveret.TableName.Length==0?"Table_AX":dtNeedCoveret.TableName；
             dtNeedCoveret.WriteXml(tw)；
             dtNeedCoveret.WriteXmlSchema(tw)；
             return tw.ToString()；
        } 
         public DataTable ConvertBetweenDataTableAndXML_AX(string xml)
        {
             System.IO.TextReader trDataTable = new System.IO.StringReader(xml.Substring(0, xml.IndexOf("<?xml")))；
             System.IO.TextReader trSchema = new System.IO.StringReader(xml.Substring(xml.IndexOf("<?xml")))；
             DataTable dtReturn = new DataTable()；
             dtReturn.ReadXmlSchema(trSchema)；
             dtReturn.ReadXml(trDataTable)；
             return dtReturn；
        }

]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=994</link><title><![CDATA[SqlServer存储过程之简单入门 ]]></title><author>admin</author><category>Oralce</category><pubDate>2008-9-25 9:30:30</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=994</guid><description><![CDATA[一、简单实例

1.首先来一个最简单的存储过程吧
CREATE PROCEDURE dbo.testProcedure_AX
AS
Ｓelect userID from USERS order by userid desc
注:dbo.testProcedure_AX是你创建的存储过程名,可以改为:AXzhz等,别跟关键字冲突就行了,AS下面就是一条SQL语句.


2.如何在ASP.NET中调用这个存储过程?
        public static string GetCustomerCName(ref ArrayList arrayCName,ref ArrayList arrayID)
        {
            SqlConnection con=ADConnection.createConnection()；
            SqlCommand cmd=new SqlCommand("testProcedure_AX",con)；
            cmd.CommandType=CommandType.StoredProcedure；
            con.Open()；
            try
            {
                SqlDataReader dr=cmd.ExecuteReader()；
                while(dr.Read())
                {
                    if(dr[0].ToString()=="")
                    {
                        arrayCName.Add(dr[1].ToString())；
                    }
                }
                con.Close()； 
                return "OK!"；
            }
            catch(Exception ex)
            {
                con.Close()；
                return ex.ToString()；
            }
        }
注:其实就是把以前
SqlCommand cmd=new SqlCommand("Ｓelect userID from USERS order by userid desc",con)；
中的SQL语句替换为存储过程名,再把cmd的类型标注为CommandType.StoredProcedure(存储过程)


3.再来个带参数的存储过程吧.
CREATE PROCEDURE dbo.AXzhz
/*
这里写注释
*/
@startDate varchar(16),
@endDate varchar(16) 
AS
 Ｓelect id  from table_AX where commentDateTime>@startDate and commentDateTime<@endDate order by contentownerid DESC

注:@startDate varchar(16)是声明@startDate 这个变量,多个变量名间用【,】隔开.后面的SQL就可以使用这个变量了.


4.如何在ASP.NET中调用这个带参数的存储过程?
 public static string GetCustomerCNameCount(string startDate,string endDate,ref DataSet ds)
{
            SqlConnection con=ADConnection.createConnection()；
//-----------------------注意这一段--------------------------------------------------------------------------
            SqlDataAdapter da=new SqlDataAdapter("AXzhz",con)；

            para0=new SqlParameter("@startDate",startDate)；
            para1=new SqlParameter("@endDate",endDate)；
            da.ＳelectCommand.Parameters.Add(para0)；
            da.ＳelectCommand.Parameters.Add(para1)；
            da.ＳelectCommand.CommandType=CommandType.StoredProcedure；
//-----------------------------------------------------------------------------------------------------------
            try
            {
                con.Open()；
                da.Fill(ds)；
                con.Close()；
                return "OK"；
            }
            catch(Exception ex)
            {
                return ex.ToString()；
            }            
        }

注:把命令的参数添加进去,就OK了.

5.如何查看SQL命令执行成功了没有.
CREATE PROCEDURE dbo.AXzhz
/*
  @parameter1 用户名
  @parameter2 新密码
*/
@password nvarchar(20),
@userName nvarchar(20)
AS
declare @err0 int
update WL_user set password=@password where UserName=@userName
set @err0=@@error 
Ｓelect  @err0 as err0

注:先声明一个整型变量@err0,再给其赋值为@@error(这个是系统自动给出的语句是否执行成功,0为成功,其它为失败),最后通过Ｓelect把它选择出来.


6.如何从后台获得这个执行成功与否的值?
下面这段代码可以告诉你答案:
    public static string GetCustomerCName()
        {
            SqlConnection con=ADConnection.createConnection()；            
            SqlCommand cmd=new SqlCommand("AXzhz",con)；
            cmd.CommandType=CommandType.StoredProcedure；
            para0=new SqlParameter("@startDate","2006-9-10")；
            para1=new SqlParameter("@endDate","2006-9-20")；
            da.ＳelectCommand.Parameters.Add(para0)；
            da.ＳelectCommand.Parameters.Add(para1)； 
            con.Open()；
            try
            {
               Int32 re=(int32)cmd.ExecuteScalar()； 
                con.Close()； 
                if (re==0)
                 return "OK!"；
                else
                 return "false"；
            }
            catch(Exception ex)
            {
                con.Close()；
                return ex.ToString()；
            }
        }

7.如何根据传入的参数判断执行哪条SQL语句?
ALTER PROCEDURE dbo.ＳelectCustomerCNameCount
@customerID int
AS
if @customerID=-1
 begin
 Ｓelect contentownerid ,userCName,count(*) as countAll from view_usercomment group by contentownerid,userCName order by contentownerid DESC
 end
else
 begin
 Ｓelect contentownerid ,userCName,count(*) as countAll from view_usercomment where contentownerid=@customerID group by contentownerid,userCName order by contentownerid DESC
 end

二、C＃中使用带返回值的存储过程

例如在向数据库添加新数据时，需要检测是否有重复
本例介绍如何把这个检测的过程放在存储过程中，并用程序调用检测的结果做出反应。
存储过程如下：
CREATE PROCEDURE DInstitute_Insert
@InstituteNO nvarchar(6),@InstituteName nvarchar(40)
 AS
declare @return int,@count int
if(ltrim(rtrim(@InstituteName))='' or ltrim(rtrim(@InstituteNO))='')
 Ｓelect @return=3--返回3表示提交的数据有空值
else
begin
 Ｓelect @count=count(1) from DInstitute where InstituteNO=@InstituteNO
 if(@count>0)
  Ｓelect @return=1--返回1表示编号有重复
 else
 begin 
  insert into DInstitute (InstituteNO,InstituteName) values  (@InstituteNO,@InstituteName) 
  if(@@error>0)
   Ｓelect @return=2--返回2表示数据操作错误
  else
   Ｓelect @return=0--返回0表示数据操作成功
 end
end
return @return
GO 

其中DInstitute 是一个学院信息表。只有InstituteNO（学院编号）、InstituteName（学院名称）两个字段。

在C＃中调用本存储过程的代码如下：
//执行插入操作
            SqlCommand com1 = new SqlCommand("DInstitute_Insert", DBcon)；
            if (com1.Connection.State == ConnectionState.Closed)
                com1.Connection.Open()；
            com1.CommandType = CommandType.StoredProcedure；
            com1.Parameters.Add(new SqlParameter("@InstituteNO",SqlDbType.NVarChar,6))；
            com1.Parameters.Add(new SqlParameter("@InstituteName", SqlDbType.NVarChar, 40))；
            com1.Parameters.Add(new SqlParameter("@return", SqlDbType.Int))；
            com1.Parameters["@return"].Direction = ParameterDirection.Returnvalue；
            com1.Parameters["@InstituteNO"].value = t_NO.Text；
            com1.Parameters["@InstituteName"].value = t_name.Text；
            try
            {
                com1.ExecuteScalar()；
            }
            catch(SqlException ee)
            {
                DB.msgbox("操作失败！"+ee.Message.ToString())；
                return；
            }
            finally
            {
                com1.Connection.Close()；
            }
            string temp = com1.Parameters["@return"].value.ToString()；
            //返回0表示数据操作成功
            //返回1表示编号有重复   
            //返回2表示数据操作错误 
            //返回3表示提交的数据有空值
            switch (temp)
            {
                case "0":
                    DB.msgbox("添加成功！")；
                    break；
                case "1":
                    DB.msgbox("编号有重复！")；
                    break；
                case "2":
                    DB.msgbox("数据操作错误！")；
                    break；
                case "3":
                    DB.msgbox("提交的数据有空值！")；
                    break；
            }
            Binding()； //刷新datagrid 

三、SqlServer存储过程的事务处理

方法一：
--测试的表   
  create   table   tb(  id   int     not   null     constraint   PK_sys_zj_fielddict   primary   key   ,aa   int)   
  --事务处理   
  begin   tran   
  insert   into   tb   values(1,1)   
  if   @@error<>0   goto   lb_rollback   
  insert   into   tb   values(1,1)   
  if   @@error<>0   goto   lb_rollback   
  insert   into   tb   values(2,1)   
  if   @@error<>0   goto   lb_rollback   
  insert   into   tb   values(2,1)   
  if   @@error<>0   goto   lb_rollback   
  insert   into   tb   values(3,1)   
  if   @@error<>0   goto   lb_rollback   
  lb_commit:   
  commit   tran   
  goto   lb_ok   
  lb_rollback:   
  rollback   tran       
  --显示结果   
  lb_ok:   
  Ｓelect   *   from   tb   
  drop   table   tb


方法二：
--创建测试表   
  create   table   tb(id   int     not   null     constraint   PK_sys_zj_fielddict   primary   key  ,aa   int)       
  --设置选项   
  SET   XACT_ABORT   on       
  --事务处理   
  begin   tran   
  insert   into   tb   values(1,1)   
  insert   into   tb   values(1,1)   
  insert   into   tb   values(2,1)   
  commit   tran       
  --显示结果   
  /*--------注意   
          如果这样写的话,后面的语句不会被执行,如果要执行后面的语句,要在这句后面加上GO,仅查询分析分析器支持,所以如果是在存储过程中,要保证commit   tran后面没有其他语句,否则出错时,其他语句不会被执行   
  -----------*/   
  Ｓelect   *   from   tb   
  drop   table   tb   

四、.Net中使用事务处理


SqlConnection myConnection = new SqlConnection("Data Source=localhost；Initial Catalog=Northwind；Integrated Security=SSPI；")； 
myConnection.Open()； 

SqlTransaction myTrans = myConnection.BeginTransaction()； //使用New新生成一个事务 
SqlCommand myCommand = new SqlCommand()； 
myCommand.Transaction = myTrans； 

try 
{ 
myCommand.CommandText = "Update Address set location='23 rain street' where userid='0001'"； 
myCommand.ExecuteNonQuery()； 

myCommand.CommandText = "Update table2 set dd='23 rain street' where userid='0001'"； 
myCommand.ExecuteNonQuery()； 

myTrans.Commit()； 
Console.WriteLine("Record is udated.")； 
} 
catch(Exception e) 
{ 
myTrans.Rollback()； 
Console.WriteLine(e.ToString())； 
Console.WriteLine("Sorry, Record can not be updated.")； 
} 
finally 
{ 
myConnection.Close()； 
}

说明：在SqlServer中，每条Sql语句都作为一个事务来执行，所以无论在存储过程，还是在.net代码中使用，执行单条Sql语句没有必要使用事务处理。

信息来源：http://www.cnblogs.com/tuyile006/

]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=993</link><title><![CDATA[C#中取得程序當前工作目錄和執行目錄的一些方法 ]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-9-20 8:44:26</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=993</guid><description><![CDATA[总结C#中得到程序当前工作目录和执行目录的一些方法 

1.   System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
     获取模块的完整路径。
2.   System.Environment.CurrentDirectory
     获取和设置当前目录(该进程从中启动的目录)的完全限定目录。
3.   System.IO.Directory.GetCurrentDirectory() 
     获取应用程序的当前工作目录。这个不一定是程序从中启动的目录啊，有可能程序放在C:\www里,这个函数有可能返回C:\Documents and Settings\ZYB\,或者C:\Program Files\Adobe\,有时不一定返回什么东东，我也搞不懂了。
4.  System.AppDomain.CurrentDomain.BaseDirectory
     获取程序的基目录。
5.  System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase
     获取和设置包括该应用程序的目录的名称。
6.  System.Windows.Forms.Application.StartupPath 
     获取启动了应用程序的可执行文件的路径。效果和2、5一样。只是5返回的字符串后面多了一个"\"而已
7.  System.Windows.Forms.Application.ExecutablePath
     获取启动了应用程序的可执行文件的路径及文件名，效果和1一样。

8.进程对象在.NET中表现为System.Diagnostics.Process类，通过调用Process.GetCurrentProcess().MainModule.FileName可获得当前执行的exe的文件名。


//正在运行的程序路径和文件名 
string _file = Application.ExecutablePath；
//正在运行的程序路径 
string _path = Application.StartupPath；
//正在运行的程序名称 
string _name = _file.Replace(string.Format("{0}\\", _path), string.Empty)； 
]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=992</link><title><![CDATA[如何將程序的Access数据库嵌入到资源中发布 ]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-9-20 8:42:19</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=992</guid><description><![CDATA[ 1        private string AccessPath = Application.StartupPath.ToString() + "\\" + "SAP_Words.dll"；
 2        private string ResourcesPath = Application.StartupPath.ToString() + "\\" + "Resources.dll"；
 3
 4       調用 WriteEmbeddedFile("SAP_Words.dll", AccessPath)；
 5        private Stream GetStream(string name)
 6        {
 7            return GetResourceAssembly().GetManifestResourceStream("資源類的命名空間."+name)；
 8        }
 9
10        private Assembly GetResourceAssembly()
11        {
12            return Assembly.LoadFrom(ResourcesPath)；
13        }
14
15        private void WriteEmbeddedFile(string name, string fileName)
16        {
17            using (Stream stream = GetStream(name))
18            {
19                FileInfo file = new FileInfo(fileName)；
20                using (FileStream fileStream = file.Create())
21                {
22                    byte[] buf = new byte[1024]；
23                    int size；
24                    while ((size = stream.Read(buf, 0, 1024)) > 0)
25                    {
26                        fileStream.Write(buf, 0, size)；
27                    }
28                }
29            }
30        }
]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=991</link><title><![CDATA[用反射方法使用户控件动态调用父页面的方法 ]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-9-20 8:41:32</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=991</guid><description><![CDATA[下面演示了用户控件调用父页面SetLaeble方法。
父页面类型用反射的方法获取，这避免了不同页面调用同样时，需要类型转换的问题（不用写很多case了:)）。

当然还有一种方法是父页面去实现一个接口，即去实现SetLabel方法，uc把this.Page转成这个接口就可以了。


用户控件:

using System.Reflection；
private void Button1_Click(object sender, System.EventArgs e)
        {
            //用反射方法动态调用父页面的方法
            System.Web.UI.Page p = this.Page；
            Type pageType = p.GetType()；
            MethodInfo mi = pageType.GetMethod("SetLabel")；
            mi.Invoke(p,new object[]{"你这个大猪猪!"})；
            
        } 

父页面： 

public void SetLabel(string str)
        {
            this.Label1.Text = str；
        } 
]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=990</link><title><![CDATA[用C#代码生成一个简单的PDF文件 ]]></title><author>admin</author><category>VS and C#</category><pubDate>2008-9-20 8:33:00</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=990</guid><description><![CDATA[using System；
using System.IO；
using System.Text；
using System.Collections；

namespace PDFGenerator
{
     /// <summary>
     /// Application : Generation of PDF file from text
     /// Author         : Pramod Kumar Singh 
     /// Date         : 25th July 2001
     ///</summary>
        
     public class PDFGenerator
     {
         static float pageWidth = 594.0f；
         static float pageDepth = 828.0f；
         static float pageMargin = 30.0f；
         static float fontSize = 10.0f；
         static float leadSize = 10.0f；
        
         //Create a PDF file.
         //PDF on Disk
         static StreamWriter pPDF=new StreamWriter("F:\\Temp\\myPDF.pdf")；
         //PDF in Memory
         static MemoryStream mPDF= new MemoryStream()；
        
         //Convert the Text Data to PDF format and write back to
         //Memory Stream
         static void ConvertToByteAndAddtoStream(string strMsg)
         {
             Byte[] buffer=null；
             buffer=ASCIIEncoding.ASCII.GetBytes(strMsg)；
             mPDF.Write(buffer,0,buffer.Length)；  
             buffer=null；
         }
        
         //Format the data length in xRef Format
         static string xRefFormatting(long xvalue)
         {
             string strMsg =xvalue.ToString()；
             int iLen=strMsg.Length；
             if (iLen<10)
             {
                 StringBuilder s=new StringBuilder()；
                 //string s=null；
                 int i=10-iLen；
                 s.Append('0',i)；
                 strMsg=s.ToString() + strMsg；
             }
             return strMsg；
         }

         //Entry Point
         static void Main(string[] args)
         {
             //Create a ArrayList for xRefs of PDF Document
             ArrayList xRefs=new ArrayList()；
             Byte[] buffer=null；
             float yPos =0f；
             long streamStart=0；
             long streamEnd=0；
             long streamLen =0；
             string strPDFMessage=null；
             //PDF Header Message
             strPDFMessage="%PDF-1.1\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
            
             //ID 1 For Containt
             //ID 2 For Length of the Stream
             //write the Text
            
             //1> Start a new Page
             xRefs.Add(mPDF.Length)；
             strPDFMessage="1 0 obj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage="<< /Length 2 0 R >>\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage="stream\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
            
             //Get the start of the stream
             streamStart=mPDF.Length；
             strPDFMessage="BT\n/F0 " + fontSize +" Tf\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             yPos = pageDepth - pageMargin；
             strPDFMessage=pageMargin + " " + yPos +" Td\n" ；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage= leadSize+" TL\n" ；
             ConvertToByteAndAddtoStream(strPDFMessage)；
            
             //Add the text data to the PDF memory stream
             strPDFMessage= "(Pramod Kumar Singh)Tj\n" ；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage= "ET\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             //Get the End of the stream
             streamEnd=mPDF.Length；
             //Get the Length of the stream
             streamLen=streamEnd-streamStart；
             strPDFMessage= "endstream\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
                    
             //Add 2 object to xRef
             xRefs.Add(mPDF.Length)；
             strPDFMessage="2 0 obj\n"+ streamLen + "\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
                        
             //Add Page to xRefs
             xRefs.Add(mPDF.Length)；
             strPDFMessage="3 0 obj\n<</Type/Page/Parent 4 0 R/Contents 1 0 R>>\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
            
             //Build the Pages
             xRefs.Add(mPDF.Length)；
             strPDFMessage="4 0 obj\n<</Type /Pages /Count 1\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage="/Kids[\n3 0 R\n]\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage="/Resources<</ProcSet[/PDF/Text]/Font<</F0 5 0 R>> >>\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             strPDFMessage="/MediaBox [ 0 0 "+ pageWidth + " " + pageDepth + " ]\n>>\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
            
             //Add font to xRefs
             xRefs.Add(mPDF.Length)；
             strPDFMessage="5 0 obj\n<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding/WinAnsiEncoding>>\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
                    
             //Add the catalog to xRefs
             xRefs.Add(mPDF.Length)；
             strPDFMessage="6 0 obj\n<</Type/Catalog/Pages 4 0 R>>\nendobj\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
                        
             //xRefs Entry 
             streamStart=mPDF.Length；
             strPDFMessage="xref\n0 7\n0000000000 65535 f \n"；
             for(int i=0；i<xRefs.Count；i++)
             {
                 strPDFMessage+=xRefFormatting((long) xRefs[i])+" 00000 n \n"；
             }
             ConvertToByteAndAddtoStream(strPDFMessage)；
             //Trailer for the PDF
             strPDFMessage="trailer\n<<\n/Size "+ (xRefs.Count+1)+"\n/Root 6 0 R\n>>\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             //xRef location entry
             strPDFMessage="startxref\n" + streamStart+"\n%%EOF\n"；
             ConvertToByteAndAddtoStream(strPDFMessage)；
             //Write the PDF from Memory Stream to File Stream
             mPDF.WriteTo(pPDF.BaseStream)；
             //Close the Stream
             mPDF.Close()；
             pPDF.Close()；
         }
     }
} ]]></description></item><item><link>http://h31home.com/h312005/blogview.asp?ID=989</link><title><![CDATA[SQL 中 Ｓelect 语句的执行顺序 ]]></title><author>admin</author><category>Oralce</category><pubDate>2008-9-20 8:31:02</pubDate><guid>http://h31home.com/h312005/blogview.asp?ID=989</guid><description><![CDATA[    好像自已在书写 SQL 语句时由于不清楚各个关键字的执行顺序, 往往组织的 SQL 语句缺少很好的逻辑, 凭感觉 "拼凑" ( 不好意思, 如果您的 SQL 语句也经常 "拼凑", 那您是不是得好好反省一下呢?, 呵呵). 确实是爽了自己, 可苦了机器, 服务器还需要在我们的杂乱无章的 SQL 语句中寻找它下一句需要执行的关键字在哪里. 效率嘛, 由于我们的感觉神经对秒以下的变化实在不敏感, 暂且就认为自已写的 SQL 顺序无关紧要, "反正没什么变化!", 呵呵.其实服务器对每句 SQL 解析时间都会有详细记录的, 大家可以看一下自已按习惯写的 SQL 和按标准顺序写的SQL解析时间差别有多大.
   因此, 建议大家在平时工作中 SQL 语句按标准顺序写, 一是专业, 二是实用, 呵呵, 不过我觉得最主要的是心里感觉舒服.
   标准的 SQL 的解析顺序为:
   (1).FROM 子句, 组装来自不同数据源的数据
   (2).WHERE 子句, 基于指定的条件对记录进行筛选
   (3).GROUP BY 子句, 将数据划分为多个分组
   (4).使用聚合函数进行计算
   (5).使用 HAVING 子句筛选分组
   (6).计算所有的表达式
   (7).使用 ORDER BY 对结果集进行排序

   举例说明: 在学生成绩表中 (暂记为 tb_Grade), 把 "考生姓名"内容不为空的记录按照 "考生姓名" 分组, 并且筛选分组结果, 选出 "总成绩" 大于 600 分的.
   标准顺序的 SQL 语句为: 
   Ｓelect 考生姓名, max(总成绩) as max总成绩
   from tb_Grade
   where 考生姓名 is not null
   group by 考生姓名
   having max(总成绩) > 600
   order by max总成绩
   
   在上面的示例中 SQL 语句的执行顺序如下:
   (1). 首先执行 FROM 子句, 从 tb_Grade 表组装数据源的数据
   (2). 执行 WHERE 子句, 筛选 tb_Grade 表中所有数据不为 NULL 的数据
   (3). 执行 GROUP BY 子句, 把 tb_Grade 表按 "学生姓名" 列进行分组
   (4). 计算 max() 聚集函数, 按 "总成绩" 求出总成绩中最大的一些数值
   (5). 执行 HAVING 子句, 筛选课程的总成绩大于 600 分的.
   (7). 执行 ORDER BY 子句, 把最后的结果按 "Max 成绩" 进行排序.
]]></description></item><item>
<link>http://h31home.com/rss/blogto.asp?ID=49264</link>
<title><![CDATA[视觉时尚:24孝 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-30 16:18:09</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49264</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_a214ae1baa5642799f9d7e3297ada7e2.jpg" /></p><br/>在全球化的浪潮之下，區域性的特色發展逐漸重要，在時尚這塊領域上，也有著同樣的現象。因此，我們大膽嘗試以“使用中國經典的文化元素融合現代手法”來詮釋時尚這件事，創造出中國時尚精隨。<br/><br/>原始链接:http://www.fostyle.net/archives/3939.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361371.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49265</link>
<title><![CDATA[图解浩瀚星空（二）]]></title>
<author>youhuang</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-30 14:33:16</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49265</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_672e70ceb66d480fb468c69da67eded6.jpg" /></p><br/>有很多非常漂亮的星空图片，更难得的是66为这些照片配了详细的说明，是从洋文翻译的<br/><br/>原始链接:http://www.unicornblog.cn/user1/91/25377.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361360.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49266</link>
<title><![CDATA[创意开关墙贴]]></title>
<author>yang5i</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-30 10:57:16</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49266</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_808cc984171f47b0a1297a0ea3d76ecd.jpg" /></p><br/>设计师对墙壁嵌入式插座的古板造型十分不满，便给它附加了一系列可爱的墙贴，让卡通画像附着在插座周围，让古板的它也变得活泼起来。人类把小白鼠关进笼子里驱动轮子转动的时代已经过去了，现在开始，改大转活人了。这是插画师Ziemowit Maj的一组开关贴设计，极富生趣。<br/><br/>原始链接:http://www.veering.cn/?p=3736<br/>diglog链接:http://www.diglog.com/story/technology_design_361350.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49267</link>
<title><![CDATA[镜像人生：岁月的躯壳 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-30 1:39:34</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49267</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_ecd6960eaf264fd09048ec03abe588cd.jpg" /></p><br/>《镜中回忆-A Mirrored Memory》是美国摄影师Tom Hussey为诺华制药（Novartis）旗下的一款治疗老年痴呆症的药物而拍摄的平面广告，试图通过药物和心理治疗的手段帮助患有老年痴呆症的患者重建他们年轻时的形象。而很多人认为这个系列的作品远远超过了其广告本身的价值，去掉摄影师的作品命名不说<br/><br/>原始链接:http://www.fostyle.net/archives/3928.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361348.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49268</link>
<title><![CDATA[享受影像生活！——摄影人网（fotomen.cn）]]></title>
<author>fotomen</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-29 14:23:50</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49268</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_0a08f3b37d854c58928fae5d96122c19.jpg" /></p><br/>摄影人网(www.fotomen.cn ) 是广州高至文化传播机构成员，与《摄影之友》、《摄影之友&#183；记录》、《今日人像》、《CCP》、《光线》、《今日新娘》、《影像视觉&#183；Digital Camera》、《哈苏季刊&#183；Victor》、尚图图片交易网(www.sunfotos.com ) 、高域广告公司，共同组成中国最全面的影像传媒平台。<br/><br/>原始链接:http://www.fotomen.cn/<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361325.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49258</link>
<title><![CDATA[VS 2010 Productivity Power Tools升级包（附新酷功能）]]></title>
<author>scottgu</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-29 13:45:31</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49258</guid>
<description><![CDATA[ <p>[原文发表地址]：VS 2010 Productivity Power Tools Update (with some cool new features)</p>  <p>[原文发表时间]：2010/7/19, 11:18 PM</p>  <p>&#160;</p>  <p>上个月我发表了一篇关于VS 2010 Productivity Power Tools扩展的博客—一个免费的Visual Studio 2010扩展工具箱，它附带了好几个很不错的功能。</p>  <p>最初发布的Visual Studio Productivity Power Tools工具包里包含了一批高效实用的功能—比如一个更快的“添加引用”对话框，新添及增强的代码编辑器功能，还有一些不错的IDE文档标签的改进。详情可以参见我前面的博客文章。</p>  <h3>VS 2010 Productivity Power Tools升级包</h3>  <p>昨天我们发布了VS 2010 Productivity Power Tools的一个升级包，里面添加了一些不错的功能和改进。</p>  <p>如果你的机器上已经安装了VS 2010 Productivity Power Tools，你可以通过点击Visual Studio的“工具-&gt;扩展管理器”菜单来升级到最新版本。这个菜单会弹出VS 2010扩展管理器—你可以用它来浏览和下载新的扩展。点击对话框左边的“更新”标签可以查看已安装的扩展是否有升级包可用。</p>  <p>点击“Productivity Power Tools”上的“更新”按钮，就可以下载和安装升级了。</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb.png" width="806" height="454" /> </p>  <p></p>  <p>如果你尚未安装VS 2010 Productivity Power Tools，可以在这里下载和安装它。</p>  <p>Sean写了一篇很好的文章来讲解本周升级包里所有的更新和增强，下面是其中一些亮点：</p>  <h3>工具选项的支持</h3>  <p>关于Productivity Power Tools呼声最高的一个特性就是能够分别关闭或启用工具包里单独的功能。</p>  <p>在上个月发布的版本里开关独立的功能可没那么容易。从本周的版本开始，在VS 2010的工具-&gt;选项对话框里新加了一个Productivity Power Tools的节点，通过它你可以轻易地开关某个功能。</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb_1.png" width="649" height="381" /> </p>  <p></p>  <p>除了开关独立的功能以外，你还可以编辑和微调他们的设置（例如配色方案和行为）。</p>  <h3>解决方案导航（Solution Navigator）</h3>  <p>解决方案导航是本周升级包了新加的VS 2010工具窗口。它就像一个加强版的解决方案资源管理器。它将“解决方案资源管理器”、“类视图”、“对象浏览器”、“调用层次结构”、“定位到”和“查找符号引用”的功能统统集中到了一个窗口中—酷毙了。下面是你可以用到它的两种情况：</p>  <p><u>文件 + </u><u>类型浏览器</u></p>  <p>使用解决方案导航窗口浏览项目文件的方式跟今天你使用“解决方案资源管理器”的方式是一样的。只不过不是止步于文件节点，你还可以将文件展开查看里面定义的类、函数和其它成员。点击其中一个节点，可以立即跳到对应的代码块上。</p>  <p>比如说，下图里，我们展开了一个ASP.NET MVC项目的\Controllers文件夹，接着展开AccountController.cs文件—里面定义了一个AccountController类。现在在解决方案导航窗口里我们可以钻进这个类里面查看它的成员列表—双击其中一个就会跳转到代码编辑器里它的位置：</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb_2.png" width="287" height="676" /> </p>  <p></p>  <p><u>过滤解决方案</u></p>  <p>细心的读者可能会注意到解决方案导航窗口上方的搜索文本框，你可以用它来搜索快速过滤出需要的东西。</p>  <p>比如说，下图中我键入了一个字符串“Log”—这样解决方案导航窗口会自动过滤出名称中包含“Log”的文件和成员（其它的都被隐藏起来了）。下图中过滤后的视图里包含了一个名为“LogOn.cshtml”的视图模板，“AccountController”类型里的三个“LogXYZ”函数，“AccountModel.cs”文件里的“LogOnModel”类，还有几个名称中包含“Log”的测试用例：</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb_3.png" width="318" height="644" /> </p>  <p></p>  <p>双击任何过滤结果中的文件和成员就可以在代码编辑器中找到它。</p>  <h3>快速访问（Quick Access）</h3>  <p>快速访问是VS 2010的一个新工具窗口，允许你在IDE中快速检索和执行常见任务。是否曾经努力寻找一个菜单的位置？ 是否挣扎着在“工具-&gt;选项”的摸索一个选项？交给快速访问窗口好了，它会帮你定位：</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb_4.png" width="328" height="393" /> </p>  <p></p>  <p>点击列表中任意一项就可以执行对应的命令，或找到它在IDE中相应的位置（如果是“工具-&gt;选项”里的设置的话）。</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/VS2010ProductivityPowerTools_C12F/image_thumb_5.png" width="823" height="488" /> </p>  <p></p>  <p>上图中我搜索了“format”并找到“工具-&gt;选项”所有关于格式化的设置。单击列表中的“Text Editor -&gt; C# -&gt; Formatting Lines”就可以在“工具-&gt;选项”上精确定位选项的位置。</p>  <h3>总结</h3>  <p>我只是点到了本周升级包中一点点的改进。请阅读Sean的文章来了解更多的改进，以及更详细的信息。</p>  <p>如果你还没有安装免费的VS 2010 Productivity Power Tools，我强烈建议你赶紧装上它—我想你总会找到几个你喜欢的扩展的。如果你已经安装了上个月发布的版本，升级到本周的版本也很容易，获取更多酷炫的功能—还有一些缺陷的修复和性能上的优化。</p>  <p>希望这能对您有所帮助。</p>  <p><i>附：[</i><i>除了写博客以外，我现在也使用推特（Twitter</i><i>）来及时更新状态和分享链接，您可以到这个地址“推”我一下：</i><i>twitter.com/scottgu</i><i>]</i></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p>标签：ASP.NET, Visual Studio, .NET, Community News</p><br/><hr/>博客堂源代码发布已经发布于Codeplex，邀请您来捉臭虫<img src="http://blog.joycode.com/ajaxhelper.aggbug?PostId=116037&BlogId=158" > ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49257</link>
<title><![CDATA[14个创意指甲艺术赏]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-29 12:57:48</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49257</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_0c4191e070204970a77fda21af5b3696.jpg" /></p><br/>指甲艺术也就是在手指甲上做些彩绘或者贴些什么东西，把指甲装饰的五彩斑斓，还有3D指甲艺术，因其立体感和炫目设计而越来越受世界各地美女的欢迎，不过在我看来还是觉得有点慎人。<br/><br/>原始链接:http://quweishouji.com/14-creative-nail-art-appreciation/<br/>diglog链接:http://www.diglog.com/story/culture_art_361322.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49255</link>
<title><![CDATA[菊花回形针：Desk Daisy]]></title>
<author>koodj</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-29 0:19:33</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49255</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_788311d5a15148c8801f11c0ab998612.jpg" /></p><br/>办公室白领常常喜欢在办公桌上放一盆栽调节心情，无奈的是植物在密闭的环境里很难茁壮成长，最终全都入土为安。退而求其次，我们可以把目光转移到仿制品上。<br/><br/>Desk Daisy是一盆小菊花，仔细观察你会发现那一片片花瓣是由回形针组成的，靠”花蕊“的磁性依附在一起，茎干也可以随意弯曲成你喜爱的造型。放在桌上清新有爱又实用。<br/><br/>设计师：Liz Goulet Dubois, Fred Studio<br/><br/>原始链接:http://www.kooideas.com/Article/2635.html<br/>diglog链接:http://www.diglog.com/story/technology_design_361310.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49256</link>
<title><![CDATA[日本现代剪纸艺术 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 18:10:44</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49256</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_783be3a5945c4648b53d4a0c5190b0a3.jpg" /></p><br/>浮躁的年纪，快马加鞭的社会，成天的怨天尤人，其实说回来，还是不懂得执着，不善用心体验。再普通的工作，再传统的艺术，应该都是有它的发光点的，推荐日本女艺术家Hina Aoyama带来的极致精美又巧夺天工的剪纸作品。果真是传统的手工，现代的艺术。更多图片点这里<br/><br/>原始链接:http://www.fostyle.net/archives/3893.html<br/>diglog链接:http://www.diglog.com/story/technology_design_361301.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49259</link>
<title><![CDATA[Windows Phone 7开发工具Beta版已发布]]></title>
<author>scottgu</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 15:48:02</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49259</guid>
<description><![CDATA[ <p>[原文发表地址]：Windows Phone 7 Developer Tools Beta Released</p>  <p>[原文发表时间]：2010/7/12 10:38 PM</p>  <p>&#160;</p>  <p>今天早些时候，我们发布了Windows Phone 7开发工具的Beta版本，你可以从这里下载。</p>  <p><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blog.joycode.com/images/metaapis/158/WindowsLiveWriter/WindowsPhone7Beta_DC96/clip_image002_thumb.gif" width="631" height="394" /></p>  <h3><b><u>Windows Phone</u></b><b><u>开发工具包里都有些什么</u></b></h3>  <p>在Beta版 的Windows Phone开发工具包里：</p>  <p>1. <b>适用于Windows Phone</b><b>的Visual Studio 2010</b><b>体验版</b>——一个新的、免费的Visual Studio 2010的体验版本。</p>  <p>2. <b>适用于Windows Phone</b><b>的Blend</b><b>体验版</b>——一个新的、免费的专注于Windows Phone 7开发的Blend体验版本。</p>  <p>3. <b>适用于Windows Phone7</b><b>的Silverlight</b>。</p>  <p>4. <b>适用于Windows Phone 7</b><b>的XNA Game Studio</b>。</p>  <p>在开发工具包里面已经集成了一个手机模拟器，你可以用它在笔记本或者桌面电脑上方便地开发和测试Windows Phone 7应用程序，这样就不需要一个真的手机了。它有硬件加速功能、在多点触摸显示屏上支持多点触控事件，另外在它上面调试和测试手机程序也相当的简单。</p>  <h3><b><u>为开发者准备的设备</u></b></h3>  <p>除了可以通过模拟器测试程序以外，为开发者准备的手机预先发行版在这个月也即将上市。你可以从Windows Phone 7团队的这篇博客中了解这个计划，注册并领取一个。</p>  <h3><b><u>了解更多详情</u></b></h3>  <p>前一阵子我发表了一篇很好的手把手教程，讲解了如何使用Visual Studio 2010体验版来开发一个推特（Twitter）搜索程序。它很好地演示了使用Silverlight和Visual Studio Windows Phone工具包开发一个应用程序有多简单。你可以点击这里阅读这篇文章。</p>  <p>Windows Phone 7团队今天发表的博客介绍了很多关于今天新发布版本的细节。它也提及了两个新的Silverlight控件——Panorama和Pivot控件。你可以用它们实现新的Windows Phone 7导航风格。虽然今天的Beta版本里没有包含这两个控件，但是接下来几周内发布的更新会包括它们。</p>  <p>如果你使用过以前发布的Windows Phone 7 CTP版本，请参阅Jaime的“将基于Windows Phone CTP版本的应用程序迁移到Beta版”（Migrating Applications from the Windows Phone April CTP Refresh to the Beta）。它非常详细地讲解了更新你现有代码的方法。</p>  <h3><b><u>卸载以前的CTP</u></b><b><u>版本</u></b></h3>  <p><b><font color="#ff0000">更新</font></b>：有些用户向我们报告了在卸载以前的Windows Phone 7开发工具包CTP版本时碰到了问题。Amit的这篇博客讲解了修复方法。Aaron也写了篇博客帮助你在不完全安装XNA Game Studio的时候清除它的方法。</p>  <p>希望这能对您有所帮助。</p>  <p><i>附：[</i><i>除了写博客以外，我现在也使用推特（Twitter</i><i>）来及时更新状态和分享链接，您可以到这个地址来关注我一下：</i><i>twitter.com/scottgu</i><i>]</i></p>  <p>标签：Visual Studio, .NET, Community News, Silverlight, Windows Phone</p><br/><hr/>博客堂源代码发布已经发布于Codeplex，邀请您来捉臭虫<img src="http://blog.joycode.com/ajaxhelper.aggbug?PostId=116036&BlogId=158" > ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49254</link>
<title><![CDATA[亲手钩些可爱的hellokitty造型家居用品]]></title>
<author>youhuang</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 14:12:33</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49254</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_39e0c24ef45642ba9f3e1254e44780cd.jpg" /></p><br/>最近在网上买到本由日本三丽鸥公司授权青岛出版社出版的，可爱无比的手工书——《钩针的基础——凯蒂和三丽鸥明星们的超人气形象！》。它从钩针的基础针法和简单图案开始，详细讲解怎么钩可爱的hellokitty、美乐蒂玩偶。<br/><br/>原始链接:http://www.unicornblog.cn/user1/1/25318.html<br/>diglog链接:http://www.diglog.com/story/culture_books_361295.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49252</link>
<title><![CDATA[400多个精美天气符号图标]]></title>
<author>kokotaro</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 11:05:18</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49252</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_ab4f9dc4967141f2ab0b3b6e130f1af6.jpg" /></p><br/>最近更新了很多套天气预报图标集，所以干脆整理出来方便大家使用。目前iconpng.com已经收录了400多个天气预报术语中常见的天气符号图标。<br/><br/>原始链接:http://blog.iconpng.com/?p=49<br/>diglog链接:http://www.diglog.com/story/technology_design_361288.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49253</link>
<title><![CDATA[8个为极客准备的结婚戒指]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 10:19:21</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49253</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_0d0b3c31d6014fad8f341b43e384254e.jpg" /></p><br/>结婚是人生中的重要时刻，婚戒又是结婚必不可少的，现在好像大部分都喜欢钻戒，多少克拉啊，大大的钻石啊，不过那只是有钱人玩的，下面这些极客们设计的戒指就很特别了，当然也不便宜，只是说不必一定要什么钻戒了。<br/><br/>原始链接:http://quweishouji.com/8-for-the-preparation-of-the-wedding-ring-geeks/<br/>diglog链接:http://www.diglog.com/story/life_other_361284.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49251</link>
<title><![CDATA[Adele Enersen的宝宝摄影：Mila的白日梦]]></title>
<author>youhuang</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-28 1:29:09</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49251</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_d2f0f6e341c54a0b92db3e9fbb0abe62.jpg" /></p><br/>Adele Enersen拍了个可爱的宝宝系列摄影，名为“Mila’ S Daydreams”。在这些白日梦中，哪个真正是Mila宝宝的白日梦呢？<br/><br/>原始链接:http://www.unicornblog.cn/user1/unicornblog/25359.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361277.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49263</link>
<title><![CDATA[Web系统突然爆”Asp.net ajax客户端框架未能加载“的一种可能原因（误改服务器系统时间）]]></title>
<author>flyingfish</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-27 22:22:00</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49263</guid>
<description><![CDATA[ <p>作者: flyingfish 发表于 2010-07-27 22:22 原文链接 阅读: 898 评论: 4</p><p>为便于将WebGIS应用系统方便的部署在笔记本上做演示用，特意制作了一个虚拟机服务器环境，需要时只要把虚拟机vhd,vmc文件（Virtual PC 2007）拷贝到目标机器，安装虚拟机程序即可，省去了部署GIS服务器、WEB服务器、数据库等一系列软件，非常方便快捷。此方法一经试用用，备受欢迎，已多次在用于在笔记上部署复杂应用系统。</p>
<p>&nbsp;</p>
<p>近日将一配置好的Web应用程序以服务器虚拟机形式部署在一台笔记本上，罕见的遇到问题。部署好后，在本上访问，IE7.0连爆三个脚本错误：</p>
<p>1、Asp.net ajax客户端框架未能加载</p>
<p>2、&lsquo;Sys&rsquo;未定义</p>
<p>3、&lsquo;Sys&rsquo;未定义（但不在同一行）</p>
<p>&nbsp;</p>
<p>试验：</p>
<p>1、用另外机器的ie、ff、ietester等访问均存在问题；</p>
<p>2、将同一虚拟机部署在其他数台计算机上均未发现此问题（此前已在数台笔记本上跑过，未发现问题）；</p>
<p>3、经Baidu、Google后，试验了：改webconfig，关防火墙、关杀毒、配置ie安全选项，设置iis身份认证等均未解决问题。</p>
<p>&nbsp;</p>
<p>经以上试验，采用排除法，可以排除不是虚拟机的问题、不是浏览器问题，只可能是笔记本环境的问题。</p>
<p>而笔记本是新的X200，正版XP系统，之前在同样环境机器上部署过几次都未发下问题。</p>
<p>&nbsp;</p>
<p>崩溃之际，只有打算用一个正常情况下的机器的XP系统Ghost笔记本的系统。</p>
<p>最后时刻再次查看出错网页源码，将类似<span style="background-color: #ffff00;">&ldquo;&lt;script src="http://www.cnblogs.com/ScriptResource.axd?d=jNIytBNJCfUTy70eBg_LNlQ9wgtGeS579E4Uf__GgQPICXHl8yDxXLmmzSKUxulSOHo4joq_PpUDjHshbgRnkSDrwSc-SLcpSHxCVi8jHMo1&amp;amp;t=ffffffffdcd72ae2" type="text/javascript"&gt;&lt;/script&gt;&rdquo;</span></p>
<p>语句放在IE中执行，收到如下错误：</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp">指定的参数已超出有效值的范围。
参数名: utcDate  
说明: 执行当前 Web 请求期间，出现未处理的异常。请检查堆栈跟踪信息，以了解有关该错误以及代码中导致错误的出处的详细信息。  

异常详细信息: System.ArgumentOutOfRangeException: 指定的参数已超出有效值的范围。
参数名: utcDate

源错误:  

执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。   

堆栈跟踪:  

[ArgumentOutOfRangeException: 指定的参数已超出有效值的范围。 参数名: utcDate] System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate) +3352419 System.Web.HttpCachePolicy.SetLastModified(DateTime date) +47 System.Web.Handlers.AssemblyResourceLoader.System.Web.IHttpHandler.ProcessRequest(HttpContext context) +1904 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +358 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +64   


--------------------------------------------------------------------------------
版本信息: Microsoft .NET Framework 版本:2.0.50727.1433; ASP.NET 版本:2.0.50727.1433  
</pre>
</div>
<p>&nbsp;</p>
<p>再次将&ldquo;<span style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; white-space: pre;">HttpCachePolicy.UtcSetLastModified</span>&rdquo;作为关键字Google到这篇篇帖子&ldquo;asp.net utcDate 指定的参数已超出有效值的范围。求具体解决方法！"http://topic.csdn.net/u/20090305/12/abfaf0b3-e0ad-46f7-b64c-a9df9d336ec5.html</p>
<p>其中关键一段如下：</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;collapse:true;">因为通常这时候网页并不会加载错误，所以我们可以很明确的知道并不是页面生命周期内发生了异常。如果是脚本资源，通常我们打开IE的脚本调试功能会弹出对象无法初始化的错误以及一些脚本异常。如果是css文件则会出现样式丢失的现象。既然不是页面生命周期内发生了错误，我们没有理由去检查代码，特别是当代码曾一度辉煌，我们更没有理由去那么怀疑。这时候我们有理由想到托管我们代码的IIS，仔细观察提示我们应该对utcDate有一个比较深的印象。如果我们的资源是在未来创建的呢？oh，这不可能，但是当我们将系统的时间改成比资源文件的创建时间更早的时候就有理由相信这一切就成为可能了。

解决方案：

1、通过修改服务器系统时间，让其比Assembly的时间要晚，则可以了。（这适合于Assembly是别人创建的时候，当然也适合自己拥有源码的时候）。

2、通过修改Assembly的创建时间，让其早于服务器的时间，则可以了。（这适合于服务器是别人的，当然也适合于服务器是自己的情况）。
</pre>
</div>
<p>赶快查看笔记本系统时间，晕倒！竟然是2006年7月1日，今天的正确日期是2010年7月27日啊。不知道谁改的，害我晚上加班，找到他打屁股。</p>
<p>改了时间，一切复归正常。</p>
<p>&nbsp;</p>
<p>总结原因，就和上边引用的一样：客户端Assembly缓存机制依赖Assembly时间戳，实践中务必保证服务器当前时间大于所依赖类库的创建时间。</p>
<p>&nbsp;</p>
<p>参考资料：</p>
<p>1、http://topic.csdn.net/u/20090305/12/abfaf0b3-e0ad-46f7-b64c-a9df9d336ec5.html</p>
<p>2、http://blog.csdn.net/lvzhqi/archive/2009/03/02/3949459.aspx</p><img src="http://www.cnblogs.com/flyingfish/aggbug/1786379.html?type=1" width="1" height="1" alt=""/><p>评论: 4　查看评论　发表评论</p><p>程序员找工作，就在博客园</p><hr/><p>最新新闻：<br/>· Chrome 扩展开发者之最爱：”My Extensions” 扩展<span style="color:gray">(2010-07-30 08:50)</span><br/>· Perl 6实现Rakudo Star发布首个版本<span style="color:gray">(2010-07-30 08:49)</span><br/>· Adobe推创意大学计划 将为设计师开发者等人群提供考试认证<span style="color:gray">(2010-07-30 08:48)</span><br/>· 微软首席运营官：我们是云计算领域领导者<span style="color:gray">(2010-07-30 08:45)</span><br/>· 甲骨文涉嫌诈骗美国政府遭司法部起诉<span style="color:gray">(2010-07-30 08:26)</span><br/></p><p>编辑推荐：找优秀程序员，就在博客园<br/></p><p>网站导航：博客园首页&nbsp;&nbsp;个人主页&nbsp;&nbsp;新闻&nbsp;&nbsp;闪存&nbsp;&nbsp;小组&nbsp;&nbsp;博问&nbsp;&nbsp;社区&nbsp;&nbsp;知识库</p> ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49250</link>
<title><![CDATA[Toscoquattro的18个极简卫浴设计 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-27 15:56:06</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49250</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_736ef6d0f4224268b68556eb2a2f4bab.png" /></p><br/>顶尖卫浴设计公司TOSCOQUATTRO，一直以来都是国际上举足轻重的行业领袖，他们的极简卫浴设计看上去是有那么点简单与低调的感觉，其实透露出来的是尊贵与卓越，这18个卫浴作品展现出来的难道不正是你我都曾经梦到过的吗？朋友，享受生活很重要，即便现在还没有这个条件，至少不能磨灭那种向往的感觉。<br/><br/>原始链接:http://www.fostyle.net/archives/3856.html<br/>diglog链接:http://www.diglog.com/story/technology_design_361251.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49245</link>
<title><![CDATA[10个创新实用的有关牙齿保洁的产品]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-27 11:30:39</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49245</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_5ebb16fd2aad45a6b9e714c581711c83.jpg" /></p><br/>我在这里说的有关牙齿保洁的产品主要是指牙刷，牙线，牙刷架以及消毒剂等，这些东西对于我们来说还不是很常见的吧，而且有的也用不起，虽然对牙齿健康很好，可惜资金有限啊。<br/><br/>原始链接:http://quweishouji.com/10-innovative-and-practical-products-related-to-teeth-cleaning/<br/>diglog链接:http://www.diglog.com/story/technology_mods_361235.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49246</link>
<title><![CDATA[Windows7小技巧之六[快速自动登录]]]></title>
<author>xjyzhenai</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-27 9:40:38</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49246</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_d013b56b39b84ef8984268f41eb75e75.png" /></p><br/>操作系统一般咱们都会设密码。但有时也觉得每天早上打开电脑，还要输入密码，挺麻烦的。能不能开了电脑，去泡杯茶回来，桌面就已经呈现在眼前了？在Windows7下该如何操作呢？<br/><br/>　　首先同时按下“Windows+R”快捷键调出运行命令窗口，然后在窗口中输入“control userpasswords2”后回车。这时Windows 7中的用户帐号（User Accounts）窗口会自动弹出，紧接着去掉 “要使用本机，用户必须输入用户名和密码”前的勾选，最后点击应用按钮就会立即弹出一个自动登录窗口（自动登陆）在你面前。现在将你的帐户密码信息输入其中，确认以后 Windows 7系统就可以自动记住你的登录帐号，当你再次进入系统的时候，它就会自动为你登录而不需要你重新输入信息了。从此，你只需开机后坐享其成就可以啦！<br/><br/>image<br/><br/>小提示：<br/><br/>　　这样做虽然方便了，但是有一定的安全隐患。如果第一个看到桌面的不是你呢？<br/><br/>　　此方法对于XP同样有效。<br/>Technorati 标签: windows7<br/><br/>原始链接:http://www.xtit.net/post/2161/<br/>diglog链接:http://www.diglog.com/story/technology_internet_361232.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49247</link>
<title><![CDATA[300+免费的纹理下载 &#171； gooosenWeb]]></title>
<author>gooosen</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-27 2:16:15</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49247</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_b037ceb3bd804df6aa6bc47a0c3924f2.jpg" /></p><br/>这次，这里我们分享300+免费的纹理，提供下载。希望能对你以后的设计提供帮助。<br/><br/>原始链接:http://www.gooosen.com/?p=658<br/>diglog链接:http://www.diglog.com/story/technology_design_361228.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49248</link>
<title><![CDATA[10款非常赞的酷炫键盘]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-26 17:59:24</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49248</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_c429e587505f49de90a171c8f37be0fb.jpg" /></p><br/>随着电脑的发展，键盘也在不断的改进，设计的更合乎现代人的习惯，而且功能也挺多的，下面这些键盘都很酷的说，相信一定有你想要的。<br/><br/>原始链接:http://quweishouji.com/10-great-praise-of-the-cool-keyboard/<br/>diglog链接:http://www.diglog.com/story/technology_hardware_361219.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49260</link>
<title><![CDATA[7月9号的精选好文链接]]></title>
<author>scottgu</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-26 16:06:57</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49260</guid>
<description><![CDATA[ <p>[原文发表地址]：July 9th Links: ASP.NET, ASP.NET MVC, jQuery, Silverlight, WPF, VS 2010</p>  <p>[原文发表时间]：2010/7/9, 12:33 AM</p>  <p>&#160;</p>  <p>这里是上次我的精选好文链接系列。另外我同时在写其他的博客系列，请参看VS 2010和.NET 4系列和ASP.NET MVC 2系列。</p>  <h3>ASP.NET</h3>  <p>· 扩展ASP.NET输出缓存（Extending ASP.NET Output Caching）：Scott Matchell写了一篇很好的文章，探讨了如何利用ASP.NET 4中可扩展的缓存提供程序API来实现一个更强大的输出缓存机制。另外你也可以通过阅读我的这篇文章来了解ASP.NET 4中对输出缓存的改进。</p>  <p>· 安装和配置Windows Server AppFabric及“高速”内存缓存（Installing and Configuring Windows Server AppFabric and “Velocity” Memory Cache）：Scott Hansleman有一篇不错的博客文章描述了安装和配置Windows Server AppFabric的方法。Windows Server AppFabric由微软免费在应用程序服务器中提供。在不到10分钟的时间里，你就可以启用它的“高速”内存缓存，并应用在ASP.NET程序中。</p>  <p>· 防止用户在文本框中拷贝粘贴文本（Preventing Users From Copying Text From and Pasting It Into TextBoxes）：Scott Mitchell有一篇很有用的文章，讨论了在ASP.NET表单（Forms）里禁用拷贝粘贴的方法。如果你想要防止用户在注册时无意中复制了错误的电邮地址（本应手动输入两次），这个方法就很有帮助。</p>  <p>· 使用Google地图API创建一个ASP.NET便利店定位程序（Building a Store Locator ASP.NET Application Using Google Maps API）：Scott Mitchell写了一系列很赞的文章来探讨如何在ASP.NET程序中集成Google Map API，实现便利店定位服务。有兴趣的话请接着看系列里的续集和续续集<u><u>[i]</u></u>。</p>  <p>· ASP.NET 4在SEO方面的改进（ASP.NET 4 SEO Improvements）：Scott Mitchell的一篇酷博，讲解了ASP.NET 4里面在搜索引擎优化（SEO）方面的一些功能改进。另外也可以看看我之前关于这个主题的文章。</p>  <p>· 更多关于SQL Compact4的细节知识（More details about SQL Compat Edition 4）：Rob在他的一篇博客文章中发表了更多关于新近发布的SQL CE 4.Beta的详细信息，SQL CE既可以独立安装，也可以集成在WebMatrix里。通过SQL CE，你可以将数据库植入在ASP.NET程序中。我发表了一篇文章介绍了它的概况。</p>  <h3>ASP.NET MVC</h3>  <p>· ASP.NET MVC技术在线研讨会（Online ASP.NET MVC Conference）：Eric Hexter分享了7月22号举办的免费的ASP.NET MVC虚拟在线研讨会的一些细节。你可以免费参加，另外也不需要长途跋涉就能出席会议。</p>  <p>· ASP.NET MVC视图守则（Rules for ASP.NET MVC Views）：Chris有一篇好文谈论了在ASP.NET MVC程序中创建和使用视图模板的推荐做法。</p>  <p>· ASP.NET MVC 2本地化编程指南（ASP.NET MVC 2 Localization Guide）：Adam的这篇酷博描述了使用ASP.NET MVC创建本地化程序的方法。</p>  <p>· 在ASP.NET MVC和AJAX中防止请求伪造攻击的诀窍（Anti-Forgery Request Recipes for ASP.NET MVC and AJAX）：Dixon写了一篇绝妙好文，讲解了在ASP.NET MVC中使用AJAX时，预防常见的网站安全问题的诀窍和最佳实践。</p>  <p>· jQuery jgGrid插件（jQuery jgGrid Plugin）：Elijah有一个视频和一篇文章讲解了在ASP.NET MVC程序中使用jQuery jgGrid插件实现增删改等功能的方法。</p>  <p>· 在MVC中用ELMAH执行错误处理（Error Handling in MVC with ELMAH）：Michael写了一篇好文讲解了如何在ASP.NET MVC中安装和配置流行的ELMAH函数库。ELMAH是一个伟大的开源函数库，你可以用它来捕捉和检查在作业站点上出现的错误。 </p>  <p>· 单步跟入ASP.NET MVC源代码（Stepping into ASP.NET MVC Source Code）：Gunnar写了一篇好文讲解了如何配置Visual Studio 2010，使调试器能够轻松的单步跟入ASP.NET MVC和.NET源代码的方法。</p>  <h3>jQuery</h3>  <p>· jQuery本质论（jQuery Essentials）：很不错的在线幻灯片，为jQuery提供了极佳的概要和用法介绍。</p>  <p>· VS 2010下的jQuery 代码段（jQuery Code Snippets for VS 2010）：来瞧瞧这个很酷（并且免费）的函数库，里面有131个可以应用在VS 2010里面的jQuery代码段。酷毙了！</p>  <p>· MSDN里的7篇jQuery文章（7 jQuery Articles on MSDN）：Elijah在里面添加了他为MSDN写的7篇jQuery文章的链接。</p>  <h3>Silverlight和WPF</h3>  <p>· 使用Silverlight VS 2010工具包和WCF RIA Services创建一个简单的表单程序（Building a Simple Forms Application using the Silverlight Tool for VS 2010 and WCF RIA Services）： Mark写了一篇很赞的教程，一步步地讲解了如何使用Silverlight, VS 2010和WCF RIA Services来创建一个简单的表单程序。</p>  <p>· 使用VS 2010中的WPF和Silverlight设计器的秘诀（Tips and Tricks for Working with the WPF and Silverlight Designers in VS 2010）：Karl写了一篇文章描述了一些在VS 2010中使用WPF和Silverlight设计器时非常有用的小技巧。</p>  <p>· 在WPF和Silverlight程序里启用绑定生成器的方法（How to Enable the Binding Builder in WPF and Silverlight Applications）：Karl的另一篇好文，探讨了如何最大化利用VS 2010中数据源窗口的方法。</p>  <p>· Blend 4和Sketchflow的功能改进（Blend 4 and Sketchflow Improvements）：Christian的一篇关于Blend 4和Sketchflow最新功能改进的好文。</p>  <p>· Silverlight 4中关于双向HTTP消息的功能改进（HTTP Duplex Messaging Improvements in Silverlight 4）：一篇很好的文章，描述了Silverlight 4提供的功能改进，以允许更好的“服务器端推送”的场景，即服务器端可以不要求Silverlight客户端显式发送请求，主动推送消息给客户端。</p>  <h3>Visual Studio 2010</h3>  <p>· 代码段设计器（Snippet Designer）：一个很酷的Visual Studio 2010扩展程序，可以用来快速创建可重用的代码端。</p>  <p>· StyleCop 4.4候选版：StyleCop 4.4的最新版本已经进入候选发布阶段。StyleCop通过分析C#源代码来强制统一的编码规范。这个新版本支持C# 4.0和VS 2010。</p>  <p>· 对比SQL数据（Comparing SQL Data）：Zubair的一篇好文，演示了使用Visual Studio 2010旗舰版对比SQL数据和模式（Schema）的方法。</p>  <p>希望这能对您有所帮助。</p>  <p><i>附：[</i><i>除了写博客以外，我现在也使用推特（Twitter</i><i>）来及时更新状态和分享链接，您可以到这个地址“推”我一下：</i><i>twitter.com/scottgu</i><i>]</i></p>  <hr align="left" size="1" width="33%" />  <p>[i] 网络用语，开个玩笑，原文是Part 2和Part 3。</p><br/><hr/>博客堂源代码发布已经发布于Codeplex，邀请您来捉臭虫<img src="http://blog.joycode.com/ajaxhelper.aggbug?PostId=116035&BlogId=158" > ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49249</link>
<title><![CDATA[售价500万元的PC | 北街]]></title>
<author>jimwang</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-26 14:21:43</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49249</guid>
<description><![CDATA[ <br/>没错，你可能中了彩票头奖仍然买不起一台桌面 PC 。北街最近发现日本一家名为宙斯的定制 PC 厂商推出了两款奢华电脑产品，型号为 Jupiter 木星和 Mars 火星，售价分别为 8000 万日元和 6000 万日元，折合人民币约 540 万和 405 万。<br/><br/>原始链接:http://www.ibeijie.cn/5million-yuan-of-the-pc<br/>diglog链接:http://www.diglog.com/story/technology_other_361210.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49261</link>
<title><![CDATA[Visual Studio Scrum 1.0]]></title>
<author>Soma</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-26 11:32:22</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49261</guid>
<description><![CDATA[ <p>[原文发表地址]：Visual Studio Scrum 1.0    <br />[原文发表时间]：20 Jul 2010 12:30 PM</p>  <p>昨天我们发布了Microsoft Visual Studio Scrum 1.0，这是一个Team Foundation Server 2010的新的流程模板。该模板可以从<b>Visual Studio</b><b>库</b>，或通过<b>Visual Studio</b><b>的扩展管理器</b>下载。这次的新模板是微软自从Team Foundation Server 2005首次发布MSF Agile和MSF CMMI模板以来第一次推出新的流程模板。</p>  <p><b><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://blog.joycode.com/images/metaapis/171/WindowsLiveWriter/VisualStudioScrum1.0_A24D/clip_image001_b96741a9-f5de-4cc0-8f5f-360b3b586e5d.jpg" width="549" height="255" /></b></p>  <p>那么，为什么需要一个新的模板呢？近年来，Scrum已成为项目管理的主要方法之一，并正在迅速成为新团队和那些希望改进其现有流程的团队的默认选择。尽管Scrum团队也可以有效地利用MSF Agile模板，我们发现用户对规范的Scrum模板（自顶向下完全遵从Scrum的方法、全面使用Scrum术语的模板）的需求十分强烈。</p>  <p><b>什么是流程模板？</b></p>  <p>一个流程模板是一组文件，共同定义一个Team Foundation Server团队项目的各种流程元素。流程模板中包含您的团队的工作项、工作项查询、产品build、报告和SharePoint门户网站的定义。这其中的每一项都帮助您管理您的软件项目工作、跟踪和报告重要趋势，并最终推动高质量的软件按时发布。Microsoft Visual Studio 1.0 Scrum为从它生成的新的团队项目定义了下列内容：</p>  <p><b>工作项</b></p>  <p>· Sprint</p>  <p>· Product Backlog Item（产品积压工作项）</p>  <p>· Bug (缺陷)</p>  <p>· Task（任务）</p>  <p>· Impediment（障碍）</p>  <p>· Test Case（测试用例）</p>  <p>· Shared Steps（共享（测试）步骤）</p>  <p><b> 报告</b></p>  <p>· Release Burndown（发布计划图）</p>  <p>· Sprint Burndown（Sprint计划图，见下图）</p>  <p>· Velocity（速度 ）</p>  <p>· Build Success Over Time（一段时间内的Build成功率）</p>  <p>· Build Summary（Build汇总）</p>  <p>· Test Case Readiness（测试用例就绪度）</p>  <p>· Test Plan Progress（测试计划进度）</p>  <p><b><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blog.joycode.com/images/metaapis/171/WindowsLiveWriter/VisualStudioScrum1.0_A24D/clip_image002_450af30a-632b-4f9a-b0d6-0054963694c9.jpg" width="550" height="440" /></b></p>  <p><b>这个</b><b>模板是为谁准备的呢？</b></p>  <p>这个模板是专门为Scrum团队创建的。我们意识到，它虽然无法满足每一个团队的需求，但是我们不想陷入为在一个产品中满足所有人需求的陷阱而错过这个机会。我们的开发团队与敏捷社区领袖紧密合作，以确保模板符合Scrum团队的需要。而且模板是完全可以定制的。如果您的团队想要从一个基本的Scrum模板开始，然后逐步调整至符合您的需要，那么该模板是一个不错的选择。</p>  <p>欲了解模板内容的更多信息，请访问<b>Aaron Bjork</b><b>的博客</b>，在博客中他概述了模板的内容，以及从beta版以来的更新。</p>  <p>Namaste!</p><br/><hr/>博客堂源代码发布已经发布于Codeplex，邀请您来捉臭虫<img src="http://blog.joycode.com/ajaxhelper.aggbug?PostId=116034&BlogId=171" > ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49262</link>
<title><![CDATA[MSDN: Azure加倍]]></title>
<author>Soma</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-26 10:32:08</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49262</guid>
<description><![CDATA[ <p>[原文发表地址]：MSDN: Double the Azure    <br />[原文发表时间]：Thu, Jul 22 2010</p>  <p>今天我们正式宣布延长MSDN订阅者的Windows Azure优惠期，从最初的8个月增加一倍到16个月。</p>  <p>Windows Azure是一个灵活的云计算平台，为开发者提供按需的计算和存贮资源。通过Microsoft数据中心，您可以寄宿 (host)、扩展并管理因特网上的web应用。</p>  <p>今年一月份，我们宣布为MSDN Premium, Ultimate和BizSpark订阅者们提供Windows Azure为期8个月的推广优惠。这项服务允许MSDN订阅者利用Windows Azure平台提供的一系列服务，比如，您可以基于业务需求快速地扩展或收缩计算和存储资源，免去了服务器的采购、配置、维护等杂务。有了Azure，您只需为实际使用的资源埋单。</p>  <p>我强烈建议还没有注册这项Azure优惠的MSDN订阅者和BizSpark成员行动起来。</p>  <p>需要更多详细信息，请参考Windows Azure Platform Benefits for MSDN Subscribers页面。</p>  <p>Namaste!</p><br/><hr/>博客堂源代码发布已经发布于Codeplex，邀请您来捉臭虫<img src="http://blog.joycode.com/ajaxhelper.aggbug?PostId=116033&BlogId=171" > ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49243</link>
<title><![CDATA[7.25趣味图集（20P）]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-25 12:16:17</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49243</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_2818ba19301f44939465caf7e834285a.jpg" /></p><br/>7.25趣味图集                周末快乐，继续发布搞笑图集。<br/><br/>哈哈，机会来了<br/><br/>原始链接:http://quweishouji.com/7-25-fun-atlas-20p/<br/>diglog链接:http://www.diglog.com/story/life_other_361189.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49244</link>
<title><![CDATA[摄影：飞虎队员眼中的中国(1944年-1945年)]]></title>
<author>youhuang</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-25 12:14:52</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49244</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_86717303b8b84df8b62c9d158464af4b.jpg" /></p><br/>这本影集真实记录了飞虎队员艾伦&#183；拉森和战友威廉&#183；迪柏先生（willainm. L Dibble）拍摄到的当时中国和中国人民的一些珍贵画面，以及我们与那些英勇不屈的中国人共同战斗的难忘经历。<br/><br/>原始链接:http://www.unicornblog.cn/user1/unicornblog/25337.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361188.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49238</link>
<title><![CDATA[UI 设计师的盛宴：Web UI 设计资源大系]]></title>
<author>comsharp</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-24 20:04:49</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49238</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_720d9c63fcad4340a9f7c333c9261c90.jpg" /></p><br/>每个 Web 设计师都在 UI 设计上费尽了心血，即使这样，资源的匮乏，视野的狭窄，也常常让他们的呕心沥血之作并不为人看好，事实上，UI 设计并不需要闭门造车，很多 UI 元素是通用的。本文收集了 20 套非常前端的 UI 元素库，它们多数是可以后期修改的 PSD 或 SVG 版。<br/><br/>原始链接:http://www.comsharp.com/GetKnowledge/zh-CN/It_News_K1005.aspx<br/>diglog链接:http://www.diglog.com/story/technology_web2_361179.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49239</link>
<title><![CDATA[15个专为小孩设计的实用产品]]></title>
<author>yleo</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-24 16:40:47</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49239</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_06c559720f8c4e4c99905aeb93c806fb.jpg" /></p><br/>教育要从小抓起，因此家长对小孩玩具的选择也要有些思考和认识，下面这些是国外玩具商为小朋友设计的产品，都比较有针对性，对孩子的教育还是有很大帮助的，我们可以借鉴一下，当然能买到的也可以买来给孩子玩咯。<br/><br/>原始链接:http://quweishouji.com/15-designed-specifically-for-children-practical-products/<br/>diglog链接:http://www.diglog.com/story/technology_mods_361175.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49240</link>
<title><![CDATA[英国惊险户外超大草皮沙发 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-24 16:14:12</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49240</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_80ebdee3dc8648ebbf4a60a4e4201eb5.jpg" /></p><br/>在英国，根据信托组织的调查，人们的生活方式越来越像美国人啦，平均每周坐在沙发上的时间近43小时，户外活动大幅度减少，然后就有了这个想法，利用稻草制作一个沙发，用草皮铺盖，大小比例是普通沙发的10倍，看起来有点像是《剪刀手爱德华》片中剪出来的效果，鼓励人们多一点户外活动和提供给小朋友更健康自然的生活理念。于是笔者决定出去走走，呼吸呼吸新鲜空气<br/><br/>原始链接:http://www.fostyle.net/archives/3824.html<br/>diglog链接:http://www.diglog.com/story/technology_design_361173.html  ]]></description>
</item>
<item>
<link>http://h31home.com/rss/blogto.asp?ID=49241</link>
<title><![CDATA[The Original Hipster时尚系列：国际版犀利哥 | 佛味文革]]></title>
<author>qwill</author>
<category><![CDATA[]]></category>
<pubDate>2010-7-23 21:22:49</pubDate>
<guid>http://h31home.com/rss/blogto.asp?ID=49241</guid>
<description><![CDATA[ <p><img border=0 src="http://img.diglog.com/img/2010/7/middle_656027e1559a45f2ad55ea53aff12490.jpg" /></p><br/>犀利哥稀里糊涂的走红，网友也稀里糊涂的跟着追捧，时过境迁，烟消云散。<br/><br/>原始链接:http://www.fostyle.net/archives/3816.html<br/>diglog链接:http://www.diglog.com/story/culture_photograph_361159.html  ]]></description>
</item>


</channel>
</rss>
