May 2007 - Posts
今天早上我在处理一个数据库死锁的异常时候,怡红公子给我的其中一个建议就是使用 NOLOCK 或者 READPAST 。我在使用后特整理有关 NOLOCK 和 READPAST的一些技术知识点到本篇博客:
对于非银行等严格要求事务的行业,搜索记录中出现或者不出现某条记录,都是在可容忍范围内,所以碰到死锁,应该首先考虑,我们业务逻辑是否能容忍出现或者不出现某些记录,而不是寻求对双方都加锁条件下如何解锁的问题。
NOLOCK 和 READPAST 都是处理查询、插入、删除等操作时候,如何应对锁住的数据记录。但是这时候一定要注意NOLOCK 和 READPAST的局限性,确认你的业务逻辑可以容忍这些记录的出现或者不出现:
简单来说:
NOLOCK 可能把没有提交事务的数据也显示出来.
READPAST 会把被锁住的行不显示出来
不使用 NOLOCK 和 READPAST ,在 Select 操作时候则有可能报错误:事务(进程 ID **)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。
下面就来演示这个情况。
为了演示两个事务死锁的情况,我们下面的测试都需要在SQL Server Management Studio中打开两个查询窗口。保证事务不被干扰。
演示一 没有提交的事务,NOLOCK 和 READPAST处理的策略:
查询窗口一请执行如下脚本:
CREATE TABLE t1 (c1 int IDENTITY(1,1), c2 int)
go
BEGIN TRANSACTION
insert t1(c2) values(1)
在查询窗口一执行后,查询窗口二执行如下脚本:
select count(*) from t1 WITH(NOLOCK)
select count(*) from t1 WITH(READPAST)
结果与分析:
查询窗口二依次显示统计结果为: 1、0
查询窗口一的命令没有提交事务,所以 READPAST 不会计算没有提交事务的这一条记录,这一条被锁住了,READPAST 看不到;而NOLOCK则可以看到被锁住的这一条记录。
如果这时候我们在查询窗口二中执行:
select count(*) from t1 就会看到这个执行很久不能执行完毕,因为这个查询遇到了一个死锁。
清除掉这个测试环境,需要在查询窗口一中再执行如下语句:
ROLLBACK TRANSACTION
drop table t1
演示二:对被锁住的记录,NOLOCK 和 READPAST处理的策略
这个演示同样需要两个查询窗口。
请在查询窗口一中执行如下语句:
CREATE TABLE t2 (UserID int , NickName nvarchar(50))
go
insert t2(UserID,NickName) values(1,'郭红俊')
insert t2(UserID,NickName) values(2,'蝈蝈俊')
go
BEGIN TRANSACTION
update t2 set NickName = '蝈蝈俊.net' where UserID = 2
请在查询窗口二中执行如下脚本:
select * from t2 WITH(NOLOCK) where UserID = 2
select * from t2 WITH(READPAST) where UserID = 2
结果与分析:
查询窗口二中, NOLOCK 对应的查询结果中我们看到了修改后的记录,READPAST对应的查询结果中我们没有看到任何一条记录。
清除测试环境方法参看演示一。
参考资料:
Using NOLOCK and READPAST table hints in SQL Server
http://topic.csdn.net/t/20060905/14/4999881.html
上一个版本还是去年十一月份发布的,现在终于等到新的更新了。开心过去一直使用一个Internal Dogfood的版本,有很多小Bug,比如发布的时候会报一个类型转换错误,让开心苦不堪言,不过作为Dog foot,还是不错的。
现在这个版本界面更加清新,安装过程也非常棒,最主要的是:它已经开始提供中文版了。虽然很多翻译,开心感觉很不满意,比如将“Tag”翻译为“标记”,我的天呐!做翻译的这哥们是不是从来不写Blog呀?
下图就是这个新软件的截图,想下载可以从http://get.live.com/betas/writer_betas 得到,同时还可以下载Windows Live Mail。
我有一个比较Crazy的Idea,目前很多网友喜欢在博客中发布一些动态化内容,比如视频或者一些小型的游戏内容,可否让Windows Live Writer支持Silverlight发布?甚至支持Popfly提供的Mash-up的聚合内容?如果是这样,博客就可以更加动态化了:)
《The Architecture Journal》介绍
《The Architecture Journal》是微软公司为架构师准备的一顿丰盛的大餐,其中主要探讨进行架构设计时的一些常见问题以及最佳实践,每两个月一期。感兴趣的朋友们可以到Free Print Subscriptions这里免费索取。
这里我摘要翻译了《The Architecture Journal》最新发布的第11期中文章的主要内容,点击标题可以直接阅读内容,希望对朋友们有所帮助。
对于以往期刊,朋友们可以到这里下载其PDF版本(其中有一期提供了中文版,呵呵)。若想为《The Architecture Journal》撰写文章,也可以到这个页面了解更多信息。
Mass-Hosting High-Availability Architectures (高可靠性集群架构)
by Shaun Hirschman, Mathew Baldwin, Tito Leverette, and Michael Johnson
可扩展性和高可靠性是服务器集群架构中极为重要的一处。无论作为开源软件工程师、商业解决方案的使用者还是微软公司的IT部门工程师,对于这两个需求都没有什么“放之四海皆真理”的银弹。这篇文章就将专注于探讨创建可扩展、可靠、安全并易于维护的环境所需要的点点滴滴——一切都是为了提供高可靠性(high availability,HA)。
Delivering End-to-End High-Productivity Computing(创建端对端的高效能计算)
by Marc Holmes and Simon Cox
在当今,执行复杂的计算操作以及工程计算并不仅仅简单地如购买一台超级计算机那样简单。虽然传统意义上HPC表示的是“高性能计算,high-performance computing”,但我们认为在真实世界中HPC应该表示“高效能计算,high-productivity computing”。“高效能计算”包含的内容非常广泛,例如强大的计算和数据处理能力、良好的工具、技术、平台及其协调、执行和监视过程等。
在实现工程、科学方面“高效能计算”时我们将会遇到很多挑战。本文就将基于一些常见的需求对这类问题进行讨论,力求覆盖最常见的需求,给出供参考的范例。
Test-Driven Infrastructures(测试驱动的基础架构设计)
by Mario Cardinal
IT公司的主要职责均可以归为以下两种:“创建”和“运行”软件。这两个方面中的每一个都需要不同的能力。在公司的组织结构图中,“创建”和“运行”之间的隔阂非常大。以架构师的角度,应用程序架构师负责软件开发(创建),而基础框架架构师则专注于软件的执行(运行)。作为应用程序架构师,我认为这两个团队都应该相互学习对方的经验以及最佳实践方法。基础架构团队应该从软件开发团队中学习的一个重要经验就是用测试脚本表达架构具体实现。
Architecture Journal Profile: Don Ferguson(Architecture Journal每期一星:Don Ferguson)
本期的Architecture Journal每期一星中,我们荣幸地邀请到了Don Ferguson——一位微软公司的Technical Fellow(这是微软公司中搞技术所能达到的最高水平,待遇、地位等均相当于VP——Dflying注)。我们采访了Don Ferguson几个关于职业发展的问题,希望能够对那些想要成为架构师或对架构感兴趣的朋友们有所帮助。
Conquering the Integration Dilemma(克服集成难题)
by Jim Wilt
基于框架的可扩展架构非常流行——从门户网站到电子商务、从内容管理到消息通讯。这样的框架好用吗?大多数情况下确实不错。我们很容易地列举出一大堆基于这样框架所建立的非常成功的应用程序。这类框架提高了生产率、增强了软件质量、带来丰富的功能并减少了占领市场所需要的时间。
这样,为什么集成解决方案不考虑提供同样的改进呢?无论我怎样努力地将集成解决方案与现有工具或框架结合起来,却都很难达到结合Web应用程序或门户网站那样的效果。这正是我对“集成难题(Integration Dilemma)”的定义。
Ontology and Taxonomy of Services in a Service-Oriented Architecture (面向服务架构中服务的本体论和分类学)
by Shy Cohen
这篇论文分析了面向服务架构(SOA)中服务的本体论和分类学。其中讨论了各种不同类型服务的本质以及相互关系,描述了通用SOA系统的蓝图,并提供了一些创建和管理服务时的指导建议。本文提出的本体论和分类学有助于为架构师、工程师以及商业决策者提供明晰的服务定义,为不同职责、不同组织的人们之间的交流提供良好的便利条件。
Versioning in SOA(在SOA架构中处理版本变化)
by Boris Lublinsky
面向服务架构(Service-oriented architecture,SOA)在当前的企业架构中如日中天。SOA允许若干个开发团队并行开发同一个系统,每个团队可以自行确立其发布、维护的时间表。在本文中,我将分析在SOA架构中处理版本变化的方法,力求在实现服务时不影响到现有功能,为SOA带来更加松散耦合的实现方式。
不知疲倦的“通向分享”培训团队将在“SharePoint普及日”之后隆重推出首次SharePoint系统培训!
此次培训将分为两个部分:
1、为期3天的SharePoint应用管理培训(2007年6月22/23/24日)
| 日期 | 课程概要 |
| 2007年6月22日 | MOSS2007概述 SharePoint基础应用(上) SharePoint基础应用(下) MOSS2007配置与管理 |
| 2007年6月23日 | MOSS2007搜索的配置与使用 MOSS2007企业内容管理解决方案 MOSS2007Web内容管理 |
| 2007年6月24日 | BDC业务数据目录应用 Excel Services 应用 SharePoint Designer应用 MOSS2007中的工作流 |
2、为期2两天的SharePoint开发培训(2007年6月30日/7月1日)
| 日期 | 课程概要 |
| 2007年6月30日 | SharePoint开发概览 SharePoint对象模型揭秘:编程访问列表与文档库 SharePoint事件处理程序开发 SharePoint站点定义 |
| 2007年7月1日 | 在SharePoint平台上开发和部署Web部件 SharePoint平台上的工作流开发 SharePoint自定义列表字段类型 |
应用管理部分详细课表
开发部分详细课表
这次培训将由我跟了不起的Erucy(杜伟)主讲。
地点设在北京市海淀区知春路108号豪景大厦A座901-904室(北京三达培训基地)
收费标准为RMB1000/人天,如果同时报名5天的课程,可以打9折
详细内容参考这里:http://www.colladec.com/content.aspx?ID=17
想直接报名的话,点击这里:http://www.colladec.com/class.aspx

很好玩的是看到了Silverlight目前在国内受到了很多开发者的热情拥护,“自由、创新、研究、探索”先生在Google Groups里面创建了一个讨论组,开张不到一个月,就有176名成员参与。而Silverlight中文社区也很快就开张了,当然,到现在为止,我还不知道站长是哪位,如果是您,请您在Comments里面说一声。嘿嘿,我还得向你收小道消息费用,估计你之所以抢注到这个名字,和我这个贴子还是有一些关系的。
8. Silverlight为什么不支持中文?有没有别的途径可以解决这个问题呢?
问题描述:我相信凡是准备采用Silverlight技术或者正在使用Silverlight构建应用程序的开发者,很多人已经开始怨声载道了,为什么Silverlight不支持中文(严格来说,是中日韩等字体)?其实原因很简单,这是一个法律范畴的问题,因为每个字库都有其版权信息,而且大部分字库是不允许转移使用的(比如常见的将Vista中的微软雅黑字体复制到XP或者手机上使用应该是非法的)。
解决方案一:请参见http://blog.joycode.com/joy/archive/2007/04/06/100553.aspx中的第二项解答,即使用Glyph来代替TextBlock;但这种解决方案存在很多问题,即Glyph本身不支持换行等操作,意味着你只能把它当作标签字体来使用,而无法用其来显示正文。另外,每次浏览这个页面时,都需要下载完整的字体文件,请注意,仅微软雅黑字体(不含粗体部分)就有15M左右大小。虽然现在使用宽带的人员越来越多,但仍然是一个非常大的负担。
解决方案二:使用ODTTF文件,所谓的ODTTF文件,其实是XPS所带的嵌入式字体文件,这种字体会自动从原字体文件中提取所需要的字样,而不是简单的拷贝原字体的所有字样。操作方法如下:
- 首先使用Word或者写字板应用程序,使用您中意的字体输入你的Silverlight中所需要的文字;
- 然后在Word或者写字板当中选择“打印”功能,打印机选择Microsoft XPS Document Writer(在您安装了.NET 3.0 Framework)后会自动增加;
- XPS Document Writer本身是一个打印到文件功能,在其文件选择框中选择文件路径,并且给出相应的文件名;
- 打印完成后,在文件浏览器中找到完成的XPS文件,并且将其后缀名由".xps"修改为".zip";(其实微软的好多文件格式目前都使用了ZIP格式,比如Office 2007中的DOCX、PPTX、XLSX等等,都可以将名字改为ZIP后缀名,并且使用WinZip或者其它文件压缩程序打开)
- 直接找到这个压缩文件包中的“\documents\1\resources\fonts”中的文件,并且将其提取出来,这个文件名大部分为一个GUID加一个ODTTF后缀名;
- 将提取出来的ODTTF文件再次使用ZIP格式打包成myfonts.zip文件,并且放在您的Silverlight应用程序的根目录中;
- 假设您的XAML中的TextBlock的名字为textBlock1,那么在其后端所跟的JS文件中使用Downloader控件进行修改,大体如下:
function onLoaded(sender, eventArgs)
{
var control = sender.getHost();
var downloader = control.createObject("downloader");
downloader.addEventListener("Completed", "onCompleted");
downloader.open("GET", "myfonts.zip", true);//注意此处的myfonts.zip,根据您的实际情况进行更改
downloader.send();
}
function onCompleted(sender, eventArgs)
{
var myTextBlock = sender.findName("textBlock1"); //此处是TextBlock的名称
myTextBlock.setFontSource(sender);
myTextBlock.fontFamily = "Microsoft Yahei" ;//注意此处的字体名称,我这儿是使用的“微软雅黑”字体,您可以根据实际情况使用
myTextBlock.text = myTextBlock.text;
}
总结一下,这样的解决方案在目前应该是最有效的解决中文显示问题的,当然,在您使用部分字体时,您必须要注意一下相关的法律问题,是否取得了所使用的字体文件的跨平台授权。(该解决方案对于动态显示文本仍然无效)。
解决方案三:Silverlight产品团队目前正在致力于该问题,解决此问题目前主要的困难并不是技术问题,而主要是法律上的一些issues.
我已经为解决方案二编写了一个小型的Demo,如果您感兴趣,可以在留言中留下您的邮件,我可以发送给您。(由于本人工作繁忙,无法全部发送,所以我只会发送给前五位留下邮件地址的朋友,后来的朋友可以给这五位朋友写邮件索要)。
参考信息:
http://blogs.msdn.com/webnext/archive/2007/05/25/silverlight-font-embedding.aspx
http://wpf-e.spaces.live.com/blog/cns!2B248D261D0E0035!122.entry
SnagIt’s output for Team System lets you add screen captures to new or existing bugs with a single click. Stop trying to describe problems with tons of text – just show them. Plus, eliminate the hassle of attaching images!
How will I use this?
- Use images to give in-depth explanation of bugs or tasks.
- Save time by adding screen captures to existing work items.
- Use screen captures to illustrate design ideas.
see more:http://www.techsmith.com/snagit/accessories/teamsystem.asp
Sunmoonfire在他的新文章中介绍了如何用SharePoint Designer修改SharePoint列表数据显示样式的方法,非常适合不懂编程的IT管理人员学习!链接如下:
http://www.cnblogs.com/Sunmoonfire/archive/2007/05/22/755968.html
另外,问个问题,有谁知道怎么在自己的WebPart里Render出来一个DataViewWebPart(WSSv3)?或者根本不可能?
隐式类型变量 (Implicitly typed local variables)
象下面的代码书写就是隐式类型变量
var i = 5;
var str = “Csharp”
var numbers = new int[]{1,2,3};
var orders = new System.Collections.Hashtable();
var orders1 = new Dictionary<Guid,object>();
var i = xxx ; 的作用就是用 xxx 的类型声明为i的类型。并给i 赋值。
由于声明时候,需要依赖于等号右边的表达式,所以必须同时赋值。否则下面的书写就会报错误: Error Implicitly typed locals must be initialized
var gg;
使用 Implicitly typed local variables 时应遵守下列约束:
1. The declarator must include an initializer
声明时必须包含初始化器。
2、The initializer must be an expression. The initializer cannot be an object or collection initializer by itself, but it can be a new expression that includes an object or collection initializer.
初始化必须是一个表达式。初始化表达式不能包含它自身,
但是可以是包含一个对象或集合初始化器的一个new表达式(即匿名类型)。
3、The compile-time type of the initializer expression cannot be the null type.
初始化器表达式的编译期类型不可以是空(null)类型。
比如:
var gg = null; 这行代码就会报错误: Cannot assign '<null>' to an implicitly typed local
4、If the local variable declaration includes multiple declarators, the initializers must all have the same compile-time type.
如果局部变量声明包含了多个声明符,这些声明符必须具备同样的编译期类型。
比如如下代码:
var n = "java"
var m = 4;
var ff = m + n;
Console.WriteLine(ff);
Console.WriteLine(ff.GetType());
打印出来的信息会是:
4java
System.String
5. The initializer cannot refer to itself. (初始化中不能提起它自身)
隐式类型变量的使用范围,它可不是到处能用。仅仅可以用于下面四种情况
1. 局部变量声明
2. for 语句中变量声明)
3. using 语句初始化变量时.
4. foreach 中iterator类型声明)
比如下面代码就会报错:
class Program
{
private var tmp = "java"
}
The contextual keyword 'var' may only appear within a local variable declaration
隐式类型变量实际是编译器干的活(编译器局部变量的类型从初始化它们的表达式推导而来),所以
var i = 5; 这样的代码,编译后用 Reflector 再反编译看到的是:
int i = 5;
匿名类型(Anonymous Types)
匿名类型,是从对象初始化器自动推导和创建的元组(tuple)类型。
var o = new {Name = "Hello", Age = 23 };
var intArr = new[] {3,1,4,1,5} ;
就是 匿名类型的一种书写。
注意:
var intArr = new[] {3,1,4,1,5} ; 是匿名类型,当然也是 隐式类型变量
var intArr = new int[] {3,1,4,1,5} ; 是隐式类型变量
匿名类型 和 隐式类型变量 的区别
隐式类型变量 指我们可以通过等号右边的表达式,推断出等号左边该是那种类型。
匿名类型则是指,根据这个类型的初始化函数,我们可以推导出和创建出这个类型的实例。
这两个特性很多时候是一起作用的。
比如: new {Name = "Hello", Age = 23 }这个表达式的类型是匿名的,因此o就会变成那个匿名类型。
其中的 Name = "Hello" 又可以看作是 隐式类型变量。
不过应该没有人会用var i = 10;这样看起来像jscript的语法,所以var基本上就是为匿名类型而生 .
说明:
以上信息都是基于 Orcas Beta 1 的。也许正式版的时候,会发生变化。
参考资料:
http://blog.joycode.com/scottgu/archive/2007/05/21/102887.aspx
http://www.cnblogs.com/Dah/archive/2007/05/19/CSharp3_ImplicitlyTyped_ExtensionMethod_LambdaExpression.html
http://www.cnblogs.com/hiber/archive/2007/04/16/715641.html
http://blah.winsmarts.com/2006/05/17/demystifying-c-30--part-1-implicitly-typed-local-variables-var.aspx
http://www.kaoiki.com/read.php/17.htm
http://www.cnblogs.com/zhouyinhui/archive/2007/04/28/731574.html
http://msdn2.microsoft.com/en-us/library/ms364047(vs.80).aspx
【原文地址】 New "Orcas" Language Feature: Anonymous Types
【原文发表日期】 Tuesday, May 15, 2007 7:02 AM
在过去的2个月里,我发表了一系列贴子,讨论作为Visual Studio和.NET框架Orcas版本一部分发布的一些新的语言特性。这里是这个系列里前4个贴子的链接:
今天的贴子讨论我这个语言系列的最后一个新特性:匿名类型。
什么是匿名类型(Anonymous Types)?
匿名类型是C#和VB的方便语言特性,它允许开发人员在代码内简明地定义行内CLR类型,而不用显式地对类型定义一个正式的类声明。
匿名类型在使用LINQ做查询,转换/投影/构形数据时尤其有用。
匿名类型的例子
在我以前的查询句法贴子里,我示范了你可以通过投影来转换数据。这个LINQ的强有力的特性允许你对一个数据源(不管这个数据源是数据库,XML文件还是内存中的集合)做查询操作,然后对查询数据的结果构形成与原先数据源不同的结构或格式。
在我以前的查询句法贴子里,我定义了一个用来代表我转换过后的产品数据的MyProduct类。通过显式地定义MyProduct类,我就有了一个正式的CLR类型契约,我可以很容易地用它来把我自定义结构的产品结果在web服务间或我的应用解决方案中的多个类和程序集间传递。
但有的时候,我只想要在我当前的代码范围内查询和操作数据,我不想要另外正式地定义一个类来代表我的数据,才可以操作数据。在这种情形下,匿名类型非常有用,因为它们允许你在你的代码内,简明地定义一个新类型在行内使用。
例如,假设我使用Orcas中的LINQ到SQL对象关系映射器设计器对Northwind数据库建模,生成下列的类:
然后我就可以使用下列代码来对数据库里的产品数据进行查询,使用LINQ的投影/转换功能将数据结果定制构形成与上面的Product类有所不同的东西。但不是用一个显式定义的MyProduce类来代表从数据库获取的数据行,而是用匿名类型的特性来隐式地定义一个含4个属性的新类型来代表我定制构形的数据,象这样:
在上面的代码里,作为LINQ表达式select子句的一部分,我声明了一个匿名类型,然后由编译器自动生成带4个属性(Id, Name, UnitPrice 和 TotalRevenue)的匿名类型,这些属性的名称和类型是从查询的构形中推断出来的。
然后我使用了C#中的var这个新关键词来指代从LINQ表达式返回的这个匿名类型的 IEnumerable<T> 序列,还在后面代码的foreach语句里,对这个序列进行循环时,用var来指代其中的每个匿名类型实例。
尽管这个句法给了我动态语言一样的灵活性,我还保留了强类型语言的好处 - 包括 Visual Studio中的编译时检查和代码intellisense支持。例如,注意上面,我是如何对返回的产品序列做foreach的,对从LINQ查询推断出的带自定义属性的匿名类型,我还能得到完整的代码intellisense和编译检查。
理解var关键词
Orcas中的C#引进了var这个新关键词,在声明局部变量时可用于替代类型名。
在第一次看见var这个新关键词时,大家常有的一个错误认识是,这是个后期绑定或者无类型的变量引用(譬如,Object类型的引用或象Javascript中后期绑定的对象引用)。这并不正确,var关键词总是生成强类型的变量引用。不是要求开发人员显式地定义变量的类型,var这个关键词而是告诉编译器在变量最先声明时,从用来初始化变量的表达式推断出变量的类型。
var这个关键词可以用来引用C#的任何类型(意即它可用于匿名类型和显式定义的类型)。实际上,理解var这个关键词的最容易的方法是看一下几个将其用于常见显式类型的例子。譬如,我可以象下面这样使用var这个关键词来声明三个变量:
编译器会根据初始赋值推断出name,age和male变量的类型,在这个例子中,分别是字符串,整数和布尔值。这意味着,编译器会生成与下面代码完全一样的IL:
实际上,CLR根本不知道你使用了var这个关键词,从它的角度来看,上面2个代码例子绝对没有区别。第一个版本只不过是由编译器提供的节省开发人员几下键击的语法糖而已,让编译器做苦力推断出和声明类型名称。
除了使用var这个关键词替代内置的数据类型外,很明显地,你也可以将它用于你定义的任何自定义类型。例如,回到我以前博客贴子中的LINQ查询投影例子,这个投影使用了用来数据构形的显式的MyProduct类型,我可以用var这个关键词将其改写为:
重要注意事项:虽然我在上面使用了var这个关键词,我并没将其用于匿名类型。我的LINQ查询还是使用了MyProduct这个类型来对返回的数据做了构形,这意味着var products声明是IEnumerable<Product> products的速记而已。同样地,在foreach语句中我定义的var p变量不过是MyProduct p的速记而已。
var关键词的重要规则
因为var这个关键词产生强类型的变量声明,编译器需要能够根据它的用法推出其类型。这意味着,在用它来声明变量时,你总是需要做个初始赋值。编译器会产生一个编译错误,如果你不这么做的话:
声明匿名类型
至此,我们介绍了var这个关键词,我们可以开始用它来指代匿名类型了。
C#中的匿名类型是使用与我语言系列第一个博客贴子里讨论过的对象初始化句法同样的句法来定义的。其区别是,不是作为初始化语法的一部分来声明类型名称,而是在实例化匿名类型时,你将new关键词后面的类型名称省略掉:
编译器会分析上面的句法,自动定义一个带有4个属性的新的标准CLR类型。这4个属性的类型是根据赋给的初始值的类型来决定的。例如,在上面的例子中,Id属性被赋值了一个整数,所以编译器将生成一个类型为整数的属性。
匿名类型的实际CLR名称是由C#编译器自动生成的。CLR本身并不知道匿名类型和非匿名类型间的区别,所以两者的运行时语义是绝对完全一样的。Bart De Smet在这里写有一篇很好的博客贴子,对此做了详细讨论,如果你想知道匿名类型的确切类命名模式以及生成的IL的话。
注意上面,当你在匿名类型上键入"product." 时,你依然在Visual Studio中得到编译时检查和完整的intellisense。还注意一下,intellisense描述是如何表明它是个AnonymousType(匿名类型)的,但依然提供了完全的属性声明信息,如红线圈出的文字所示。
使用匿名类型做分层构形
匿名类型可以带来便利的一个强有力的场景是,可以用最小量的代码来轻易地对数据做分层构形投影。
例如,我可以编写下面这样的LINQ表达式,对Northwind数据库中价格大于50美元的所有产品进行查询,然后将返回的产品用以产品的ReorderLevel(库存重订购水平)来排序的一个分层结构来构形(使用了LINQ查询句法支持的group into子句):
将上面的代码在ASP.NET中运行时,我将得到浏览器显示的下列输出:
同样地,我也可以根据JOIN结果来做分层构形。例如,下面的代码生成了一个新匿名类型,它带有几个标准的产品字段属性,以及一个含有客户对特定产品所做的最新5个订单的分层的子集合属性:
注意到我是如何利落地访问分层数据的。在上面,我对产品查询进行循环,然后细钻到每个产品的最新5个订单的。你可以看到,到处都有完整的intellisense和编译时检查,即使是匿名类型上订单细节的嵌套子集合中的对象的属性上也都有。
数据绑定匿名类型
就象我在贴子前面提到的那样,从CLR的立场来说,匿名类型和显式定义的类型间绝对毫无区别。匿名类型和var关键词纯属节省代码量的“语法糖”,其运行时语义跟显式定义的类型是完全一样的。
此外,这意味着,所有的标准.NET类型反射特性,对匿名类型也是工作的,即意味着,象绑定到UI控件的特性同样工作。例如,假如我要显示我前面的分层LINQ查询的结果,我可以象下面这样在一个.aspx网页里定义一个 <asp:gridview> 控件:
上面的.aspx 含有一个gridview,它有2个标准的boundfield列,一个含有嵌套的 <asp:bulletedlist> 控件的模板字段列,我将用这个嵌套控件来显示产品的分层订单细节的子结果集。
然后,我可以编写下面这个LINQ代码来对数据库做一个分层查询,然后将定制构形的数据结果绑定到GridView来显示:
因为GridView支持对任何 IEnumerable<T> 序列的绑定,使用反射获取属性值,它对我上面使用的匿名类型依然工作。
在运行时,上面的代码会产生一个产品细节以及产品最新的订单数量的分层列表的简单网格,象这样:
很明显地,你可以把这个报表做得更丰富,更漂亮,但希望你能从中了解到,现在对数据库做分层查询是多么的容易,可以对返回的结果做你要的构形,然后对结果用编程手法操作或将其绑定到UI控件上。
结语
匿名类型是个很方便的语言特性,允许开发人员在代码内简明地定义行内CLR类型,而不用提供一个正式的类定义声明。虽然它们可以在很多场合下使用,但在使用LINQ查询和转换/构形数据时尤其有用。
这个贴子结束了我5个部分的Orcas语言系列。以后,我会发表更多的LINQ贴子,来示范如何在实战上使用所有这些新语言特性来做常见的数据访问操作(定义数据模型,查询,更新,使用存储过程,验证等等)。但我想先把这个5个部分的语言系列完成,这样我们在我将来的贴子里深入探讨时,你才会真正理解所用的底层语言构造。
希望本文对你有所帮助,
Scott
无论你是否采用测试驱动开发(TDD),编写Unit test case都是重要的工作.在项目的各个阶段,我们都需要构建测试、运行测试、报告测试结果. 有很多框架为这个工作提供便利,比如大名鼎鼎的xUnit系列.今天,我准备介绍的是一个轻量级的C++ Unit Test框架:
TUT (Template Unit Tests的缩写)
大家第一个想问的问题估计就是:它和CppUnit有什么不同? 它有什么特点?
我觉得最关键的地方在于TUT是一个轻量级的框架,TUT是使用template技术写的,完全没有macro. 除去例子,它的代码一共只有两个头文件.我们完全不用build这个框架然后设置编译连接那么多麻烦,只要在编写Unit test的时候,把这两个头文件拷贝到项目目录或者设置一下头文件的包含路径就可以了.
TUT把Unit test case通过group-test的层次组织,用户可以把相似的test case放到同一个group,这个group有一个唯一的名字, group包含多个test, 包含的test数量取决于你的编译器允许的template嵌套深度.用户可以选择运行所有的
测试或者只是部分group,甚至部分test. 在每个test里面,你可以使用TUT提供的一些方法来确认
测试结果的正确性,告诉TUT这个
测试是成功还是失败.
闲话少说,估计大家喜欢眼见为实,让我们写个例子来看看:
1. 首先包含必要的头文件#include <stdio.h>
#include "tut.h"
#include "tut_reporter.h"
2. 写了一个测试class
//测试类,做的事情很简单,记住给它的最大的数字,我们就测试这个类
class max_pool
{
int m_max;
public:
max_pool(int x=5) : m_max(x){ printf("%s init max num %d\n", __func__, x); }
void try_set_value(int num) { if (num>m_max) m_max = num; }
int get_max() { return m_max; }
};
3. 写关于test group的代码 /*这个类用在test_basic里面,
我们可以用它来完成一些每个test都需要做的初始化和清理工作,
不过这里只是为了说明, 只是输出点文字
*/
class obj_init
{
public:
obj_init() { printf( "obj_init for each test\n" ); }
~obj_init() { printf( "~obj clean for each test\n" ); }
};
namespace tut
{
struct test_basic
{
max_pool m;
obj_init xxx;
};
//每个测试用例,都会重新构造和析构test_basic里面的m 和 xxx,
//假如有什么需要每个测试都需要初始化和销毁的,放在这里
typedef test_group<test_basic> factory;
typedef factory::object object;
factory tf("max_poll_test_name");//这里设置了测试group的名字
}
4. 写两个test case
namespace tut
{
/**
* Checks insert operation
*/
template<>
template<>
void object::test<1>()
{
printf("\trun test case <1>\n");
m.try_set_value(4);
ensure( m.get_max()==5 );//告诉TUT假如这里==5就是测试OK
}
template<>
template<>
void object::test<2>()
{
printf("\trun test case <2>\n");
m.try_set_value(8);
ensure( m.get_max()==8 );//告诉TUT假如这里==8就是测试OK
}
}
5.终于写到main()了,运行所有测试:
using tut::reporter;
using tut::groupnames;
namespace tut
{
test_runner_singleton runner;
}
int main()
{
reporter visi;
tut::runner.get().set_callback(&visi);
tut::runner.get().run_tests();
return 0;
}
编译...结果我用的EditPlus+cygwin组合编译出现了问题,说我的template嵌套层次太多。看看tut.h:
template <class Data, int MaxTestsInGroup = 50>
class test_group : public group_base { ...
原来是 test_group<test_basic> 缺省有50个test,也就是说编译器需要能支持50层的template嵌套,
我修改了一下typedef test_group<test_basic,15> factory; 这样编译器只要能支持15层嵌套就可以通过了。
大家注意,VC6也是无法兼容TUT的,需要VS2003或者以上版本的支持.
最后运行的结果当然是测试通过了,结果如下, 大家可以注意到struct test_basic里面对象在每个test的输出:
max_pool init max num 5obj_init for each test
run test case <1>~obj clean for each test
max_poll_test_name: .max_pool init max num 5
obj_init for each test
run test case <2>
~obj clean for each test.max_pool init max num 5
obj_init for each test
~obj clean for each test
Popfly的宗旨是给非专业人员提供一个软件开发工具, 根据Popfly网站,
http://www.popfly.ms/Overview/
Popfly可以让大家轻松建造和共享mashups,gadgets, 网页和应用。 Popfly 由两部分组成:
1。 Popfly Creator 是一套建造网页和mashup的在线视觉化工具
2。 Popfly Space 是个在线creators社区,用户可以存放和共享自己的作品,评论和修改其他用户的作品
Channel 9 有个采访开发团队和开发人员示范的录像
http://channel9.msdn.com/showpost.aspx?postid=308460
Adam Natham提供了一个screencast录像链接,进一步展示了Popfly的功能
http://go.microsoft.com/fwlink/?LinkID=91175
该项目目前还处于alpha测试阶段,还没有向大众开放。
这段时间测试了Google Analytics,感觉改版后功能增强了不少,过滤器也好用的很,收集信息比较全面。
对于其地图分析也并没有多在意,不过今天无意中发现了它的地图。。
这个是东亚,但黄色部分显示为中国:
为了更清晰一些,点进去中国:
Google Analytics也注明了是“国家/地区”,这些在List列表中应该误解不大,但是显示到地图的话,这样总归不是一个很妥当的做法。
目前能找到的SharePoint资源最全面的(繁体)中文网站之一!
站长为享誉QQ群组的“十一”先生!
http://sharepoint.idv.tw/Pages/default.aspx
另外,发现了在事件处理程序中虚拟管理员权限的issue,请看这篇文章的更新:一个SharePoint事件处理程序实例
More Posts
Next page »