cnblogs.com

July 2008 - Posts

开博两周年!

       时间过的真快, 无意中发现今天是自己在博客园安家两周年的日子,于是总想写点东西来标记一下。

       在这两年当中,博客园见证了自己的成长历程。从最初朋友向自己推荐博客园并让自己成为了博客园的过客,那时自己往往只是在园子里浏览别人的文章,寻找自己所需要的信息;之后便有了在园子里安家的打算了,自从在园子里安家后,自己刚开始只是写点自己的生活锁事及心情随笔并且也不希望发表出去让别人看;接下来便慢慢对自己在工作当中觉得的比较实用的资料进行了总结,并发表出去希望能够给需要的人带来一些帮助。

       在这两年当中,发现自己的思想也有了改变,从当初只在园子里“摘菜”,转变为在园子里“种菜”,觉得人不要一味的去获取,有时候也应该想想如何去奉献。自己从园子里的高人中学到了不少知识,在此特别感谢dudu、天轰穿、李天平、鸟食轩等一大堆高人们,正是由于他们的奉献,才让自己能够花尽量少的时间,学到了尽量多的知识,相信博客园里许多朋友都会有同样的感慨吧!

       在接下来的日子里,自己将会再接再励,与博客园的朋友们一起共同进步!期待自己能够与园子里的朋友有更多的交流,相信博客园的明天会更加美好!



[新闻]中文维基百科可以访问啦
Google Tray - 谷歌客户端 0.2.2

看了小众软件上面的Google Calendar Tray介绍,觉得比较好用,但是只能显示日历显得有点单薄,并且一个小软件需要安装几十M的.net framework,所以我用delphi参照这个软件写了一个,同时支持gmail、日历、阅读器和在线翻译, 软件250K左右,不需要其它任何支持库。

 

当前版本:0.2.2

更新记录

0.2.2

    增加:增加一个不属于google的任务管理工具http://www.rememberthemilk.com/

0.2.1

    修改:只允许启动一个实例。

 

下载

 



[新闻]SourceForge宣布2008年度社区选择奖
[Sharepoint2007对象模型]第三回:Web应用程序(SPWebApplication)
摘要: 在Sharepoint的管理中心创建一个网站的顺序大致如下:创建Web应用程序-〉创建网站集。所以Web应用程序是网站的一个基础,在一个Web应用程序下可以创建多个网站,本回就主要来介绍Web应用程序这个对象模型以及如何使用对象模型来创建一个Web应用程序。  阅读全文

[新闻]2008年8月1日IT博客精选
OPEN SYMMETRIC KEY scope in SQL Server
摘要: 最近我收到一些关于对称密钥有效范围的问题,特别是在模块内(存储过程)打开对称密钥。其中一个问题是,如果在存储过程内执行打开密钥(OPEN SYMMETRIC KEY)的操作,而退出存储过程前没有将密钥关闭,会导致密钥“泄露”到模块以外。在BOL的OPEN SYMMETRIC KEY(在备注下方)文章中,我们已经写明,打开的密钥在整个会话范文内有效,而仅仅是在执行上下文内(包  阅读全文

[新闻]盛大文学:挖掘文学的2.0价值
JQ仿ebay右侧flash商品展示
摘要: 开blog很久,今天第一次发表,因为本人啊实在不喜欢写文章,唉~以前语文老是不及格。一直以来在思考,不知道学flash好还是silverlight好,结果在途中冒出了个JQ,凑用一下吧,反正我觉得未来flash或silverlight才是王道,未来……不知道是什么时候……仿www.ebay.com简单做了个展示框,ebay用来展示商品,而我是用来展示  阅读全文

[新闻]2008年8月1日IT博客精选
走进Linq-Linq to SQL How do I(1)
摘要:
走进Linq
从本篇起我会用大概三篇的篇幅介绍如何使用Linq to SQL,从手写代码到利用Visual Studio 2008的Designer,Step by Step的学习如何将Linq to SQL应用到你的项目当中,提高你的生产力。如果你已经掌握了如何使用Linq to SQL,这三篇都可以略过,三篇后面我们将一起探讨Linq to SQL后面的一些事情。  阅读全文

[新闻]《华尔街日报》:Google拟设立风险投资部门
撰写自用 Confirm 方法

前言
上一篇「让 ASP.NET 也可以使用 MsgBox 方法」文章中提到如何封装 JavaScript 的 alert 方法,另一个常使用在客户端处理「询问讯息」的就是 JavaScript 的 confirm 方法,在此篇文章我们将撰写自用的 Confirm 方法,使页面的程序代码尽量不要直接去撰写 JavaScript 程序代码,以增加系统的维护性。


程序实作
我们将使用「撰写自用的 ScriptManager 来管理客户端指令码」文中提及的 TBScriptManager 类别为基础,在 TBScriptManager 类别新增处理「询问讯息」会使用到相关方法。我们在 TBScriptManager 类别新增二个 GetConfirmScript 多载方法,用以取得询问讯息相关的 JavaScript 程序代码;另新增 Confirm 方法来直接注册询问讯息的客户端指令码,以下将以实例说明这三个方法的使用时机及方式。

 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->''' <summary>
''' 客户端指令码管理。
''' </summary>

Public Class TBScriptManager

    
''' <summary>
    
''' 处理消息正文的跳脱字符。
    
''' </summary>
    
''' <param name="Message">消息正文。</param>

    Private Function ParserMessage(ByVal Message As StringAs String
        
Dim sMessage As String

        sMessage 
= Strings.Replace(Message, "'""\'"'处理单引号
        sMessage = Strings.Replace(sMessage, vbNewLine, "\n"'处理换行
        Return sMessage
    
End Function


    
''' <summary>
    
''' 取得讯问窗口的客户端指令码。
    
''' </summary>
    
''' <param name="Message">消息正文。</param>

    Public Overloads Function GetConfirmScript(ByVal Message As StringAs String
        
Dim sMessage As String
        
Dim sScript As String

        sMessage 
= ParserMessage(Message)
        sScript 
= String.Format("if (confirm('{0}')==false) {{return false;}}", sMessage)
        
Return sScript
    
End Function


    
''' <summary>
    
''' 取得讯问窗口的客户端指令码。
    
''' </summary>
    
''' <param name="Message">消息正文。</param>
    
''' <param name="TrueScript">响应 true 时要执行的客户端指令码。</param>
    
''' <param name="FalseScript">响应 false 时要执行的客户端指令码。</param>

    Public Overloads Function GetConfirmScript(ByVal Message As String, _
        
ByVal TrueScript As StringByVal FalseScript As StringAs String
        
Dim sMessage As String
        
Dim sScript As String

        sMessage 
= ParserMessage(Message)
        sScript 
= String.Format("if (confirm('{0}')){{ {1} }} else {{ {2} }}", sMessage, TrueScript, FalseScript)
        
Return sScript
    
End Function


    
''' <summary>
    
''' 询问窗口。
    
''' </summary>
    
''' <param name="Message">消息正文。</param>
    
''' <param name="TrueScript">响应 true 时要执行的客户端指令码。</param>
    
''' <param name="FalseScript">响应 false 时要执行的客户端指令码。</param>

    Public Sub Confirm(ByVal Message As StringByVal TrueScript As StringByVal FalseScript As String)
        
Dim sScript As String

        sScript 
= GetConfirmScript(Message, TrueScript, FalseScript)
        
Me.RegisterStartupScript("Confirm", sScript)
    
End Sub


End Class

 

案例一:按钮加上询问讯息,按「确定」才会引发按钮的 Click 事件
按钮加上询息讯息是常使用到的案例,例如按下删除钮时,先询问用户是否确定删除数据,当按「确定」时才会真正去执行删除动作。我们可以在 Page Load 事件中,去设定 Button.OnClientClick 属性,加入询问讯息的客户端指令码。

 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load
        Button1.OnClientClick 
= Me.BeeScript.GetConfirmScript("确定删除此笔数据吗?")
    
End Sub

 

案例二:纯客户端的询问讯息
询问讯息只是在客户端执行,并不会产生 PostBack。

 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load
        
Dim sScript As String

        sScript 
= Me.BeeScript.GetConfirmScript("纯客户端的询问讯息?""alert('按了确定')""alert('按了取消')")
        HyperLink1.Attributes(
"onclick"= sScript
    
End Sub

 

案例三:先执行伺服端程序再弹出询问讯息,依客户端响应再接续执行
例如有登打请假单储存时,执行储存完毕要弹出一个是否送审询问讯息。在 WinForm 撰写这个程序代码非常单纯,只要在储存后弹出询问讯息,等待用户响应接续执行后面的程序代码即可。可是在 WebForm 要撰写相同的功能就有点麻烦了,因为整个程序的流程是在伺服端及客户端交互运作。


请假单储存(伺服端) -> 弹出询问讯息(客户端) -> 取得客户端响应决定是否送审(伺服端)


在 WebForm 要处理这类问题,要分为二个阶段处理,第一个阶段处理「请假单储存(伺服端) -> 弹出询问讯息(客户端) 」,在下面的程序代码中,讯问讯息的响应结果无论是「确定」或「取消」都会产生 PostBack 动作传不同的参数。

 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    Protected Sub btnSave_Click(ByVal sender As ObjectByVal e As System.EventArgs) Handles btnSave.Click
        
Dim sTrueScript As String
        
Dim sFalseScript As String

        
'执行请假单储存的程序代码

        
'储存完成弹出询问讯息,__EVENTTARGET 设为 "SaveConfirm"
        sTrueScript = "__doPostBack('SaveConfirm','True')"
        sFalseScript 
= "__doPostBack('SaveConfirm','False')"
        
Me.BeeScript.Confirm("假单要送审吗?", sTrueScript, sFalseScript)
    
End Sub

 

第二阶段在 Page Load 事件处理客户端询问讯息的响应「取得客户端响应决定是否送审(伺服端)」

 



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load
        
'处理询问讯息的响应
        Dim sEventTarget As String = Me.Request.Form("__EVENTTARGET")
        
Dim sEventArgument As String = Me.Request.Form("__EVENTARGUMENT")
        
If String.Equals("SaveConfirm", sEventTarget, StringComparison.CurrentCultureIgnoreCase) Then
            
If String.Equals(sEventArgument, "True", StringComparison.CurrentCultureIgnoreCase) Then
                
'按了确定要执行的程序代码
            End If

            
If String.Equals(sEventArgument, "False", StringComparison.CurrentCultureIgnoreCase) Then
                
'按了取消要执行的程序代码
            End If
        
End If
    
End Sub

 

 



[新闻]盛大文学:挖掘文学的2.0价值
[原创] 认清自己,摆脱迷茫,不再困惑
摘要: 做雷兔的群主将近一年了,在这一年里,有好多初学者都问过同样的问题,“哪种技术有发展前景,以后赚钱多呢?”我每次听到有人问我这个问题的时候都很茫然,觉得这是一个不是问题的问题……  阅读全文

[新闻]中文维基百科可以访问啦
打造自己的LINQ Provider(上):Expression Tree揭秘

概述

在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHibernate、LINQ to Google等,大有“一切皆LINQ”的趋势。LINQ本身也提供了很好的扩展性,使得我们可以轻松的编写属于自己的LINQ Provider。

本文为打造自己的LINQ Provider系列文章第一篇,主要介绍表达式目录树(Expression Tree)的相关知识。

认识表达式目录树

究竟什么是表达式目录树(Expression Tree),它是一种抽象语法树或者说它是一种数据结构,通过解析表达式目录树,可以实现我们一些特定的功能(后面会说到),我们首先来看看如何构造出一个表达式目录树,最简单的方法莫过于使用Lambda表达式,看下面的代码:

Expression<Func<int, int, int>> expression = (a, b) => a * b + 2;

在我们将Lambda表达式指定给Expression<TDelegate>类型的变量(参数)时,编译器将会发出生成表达式目录树的指令,如上面这段代码中的Lambda表达式(a, b) => a * b + 2将创建一个表达式目录树,它表示的是一种数据结构,即我们把一行代码用数据结构的形式表示了出来,具体来说最终构造出来的表达式目录树形状如下图所示:

TerryLee_0160

这里每一个节点都表示一个表达式,可能是一个二元运算,也可能是一个常量或者参数等,如上图中的ParameterExpression就是一个参数表达式,ConstantExpression是一个常量表达式,BinaryExpression是一个二元表达式。我们也可以在Visual Studio中使用Expression Tree Visualizer来查看该表达式目录树:

TerryLee_0166

查看结果如下图所示:

TerryLee_0162

这里说一句,Expression Tree Visualizer可以从MSDN Code Gallery上的LINQ Sample中得到。现在我们知道了表达式目录树的组成,来看看.NET Framework到底提供了哪些表达式?如下图所示:

TerryLee_0161

它们都继承于抽象的基类Expression,而泛型的Expression<TDelegate>则继承于LambdaExpression。在Expression类中提供了大量的工厂方法,这些方法负责创建以上各种表达式对象,如调用Add()方法将创建一个表示不进行溢出检查的算术加法运算的BinaryExpression对象,调用Lambda方法将创建一个表示lambda 表达式的LambdaExpression对象,具体提供的方法大家可以查阅MSDN。上面构造表达式目录树时我们使用了Lambda表达式,现在我们看一下如何通过这些表达式对象手工构造出一个表达式目录树,如下代码所示:

static void Main(string[] args)
{
    ParameterExpression paraLeft = Expression.Parameter(typeof(int), "a");
    ParameterExpression paraRight = Expression.Parameter(typeof(int), "b");

    BinaryExpression binaryLeft = Expression.Multiply(paraLeft, paraRight);
    ConstantExpression conRight = Expression.Constant(2, typeof(int));

    BinaryExpression binaryBody = Expression.Add(binaryLeft, conRight);

    LambdaExpression lambda = 
        Expression.Lambda<Func<int, int, int>>(binaryBody, paraLeft, paraRight);

    Console.WriteLine(lambda.ToString());

    Console.Read();
}

这里构造的表达式目录树,仍然如下图所示:

TerryLee_0160

运行这段代码,看看输出了什么:

TerryLee_0158  

可以看到,通过手工构造的方式,我们确实构造出了同前面一样的Lambda表达式。对于一个表达式目录树来说,它有几个比较重要的属性:

Body:指表达式的主体部分;

Parameters:指表达式的参数;

NodeType:指表达式的节点类型,如在上面的例子中,它的节点类型是Lambda;

Type:指表达式的静态类型,在上面的例子中,Type为Fun<int,int,int>。

在Expression Tree Visualizer中,我们可以看到表达式目录树的相关属性,如下图所示:

TerryLee_0163 

表达式目录树与委托

大家可能经常看到如下这样的语言,其中第一句是直接用Lambda表达式来初始化了Func委托,而第二句则使用Lambda表达式来构造了一个表达式目录树,它们之间的区别是什么呢?

static void Main(string[] args)
{
    Func<int, int, int> lambda = (a, b) => a + b * 2;

    Expression<Func<int, int, int>> expression = (a, b) => a + b * 2;
} 

其实看一下IL就很明显,其中第一句直接将Lambda表达式直接编译成了IL,如下代码所示:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .maxstack  3
  .locals init ([0] class [System.Core]System.Func`3<int32,int32,int32> lambda)
  IL_0000:  nop
  IL_0001:  ldsfld     class [System.Core]System.Func`3<int32,int32,int32> 
                        TerryLee.LinqToLiveSearch.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
  IL_0006:  brtrue.s   IL_001b
  IL_0008:  ldnull
  IL_0009:  ldftn      int32 TerryLee.LinqToLiveSearch.Program::'<Main>b__0'(int32,
                                                                             int32)
  IL_000f:  newobj     instance void class [System.Core]System.Func`3<int32,int32,int32>::.ctor(object,
                                                                                                native int)
  IL_0014:  stsfld     class [System.Core]System.Func`3<int32,int32,int32> 
                    TerryLee.LinqToLiveSearch.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
  IL_0019:  br.s       IL_001b
  IL_001b:  ldsfld     class [System.Core]System.Func`3<int32,int32,int32> 
                    TerryLee.LinqToLiveSearch.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
  IL_0020:  stloc.0
  IL_0021:  ret
}

而第二句,由于告诉编译器是一个表达式目录树,所以编译器会分析该Lambda表达式,并生成表示该Lambda表达式的表达式目录树,即它与我们手工创建表达式目录树所生成的IL是一致的,如下代码所示,此处为了节省空间省略掉了部分代码:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .maxstack  4
  .locals init ([0] class [System.Core]System.Linq.Expressions.Expression`1<
                class [System.Core]System.Func`3<int32,int32,int32>> expression,
           [1] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
           [2] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0001,
           [3] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0002)
  IL_0000:  nop
  IL_0001:  ldtoken    [mscorlib]System.Int32
  IL_0006:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(...)
  IL_000b:  ldstr      "a"
  IL_0010:  call       class [System.Core]System.Linq.Expressions.ParameterExpression 
                        [System.Core]System.Linq.Expressions.Expression::Parameter(
                        class [mscorlib]System.Type,

  IL_0038:  call    class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle()
  IL_003d:  call    class [System.Core]System.Linq.Expressions.ConstantExpression 
                    [System.Core]System.Linq.Expressions.Expression::Constant(object,
                    class [mscorlib]System.Type)
  IL_0042:  call    class [System.Core]System.Linq.Expressions.BinaryExpression 
                    [System.Core]System.Linq.Expressions.Expression::Multiply(class [System.Core]System.Linq.Expressions.Expression,
                    class [System.Core]System.Linq.Expressions.Expression)
  IL_0047:  call    class [System.Core]System.Linq.Expressions.BinaryExpression
                    [System.Core]System.Linq.Expressions.Expression::Add(class [System.Core]System.Linq.Expressions.Expression,
                    class [System.Core]System.Linq.Expressions.Expression)
  IL_004c:  ldc.i4.2
  IL_004d:  newarr     [System.Core]System.Linq.Expressions.ParameterExpression
}

现在相信大家都看明白了,这里讲解它们的区别主要是为了加深大家对于表达式目录树的区别。

执行表达式目录树

前面已经可以构造出一个表达式目录树了,现在看看如何去执行表达式目录树。我们需要调用Compile方法来创建一个可执行委托,并且调用该委托,如下面的代码:

static void Main(string[] args)
{
    ParameterExpression paraLeft = Expression.Parameter(typeof(int), "a");
    ParameterExpression paraRight = Expression.Parameter(typeof(int), "b");

    BinaryExpression binaryLeft = Expression.Multiply(paraLeft, paraRight);
    ConstantExpression conRight = Expression.Constant(2, typeof(int));

    BinaryExpression binaryBody = Expression.Add(binaryLeft, conRight);

    Expression<Func<int, int, int>> lambda = 
        Expression.Lambda<Func<int, int, int>>(binaryBody, paraLeft, paraRight);

    Func<int, int, int> myLambda = lambda.Compile();

    int result = myLambda(2, 3);
    Console.WriteLine("result:" + result.ToString());

    Console.Read();
}

运行后输出的结果:

TerryLee_0159

这里我们只要简单的调用Compile方法就可以了,事实上在.NET Framework中是调用了一个名为ExpressionCompiler的内部类来做表达式目录树的执行(注意此处的Compiler不等同于编译器的编译)。另外,只能执行表示Lambda表达式的表达式目录树,即LambdaExpression或者Expression<TDelegate>类型。如果表达式目录树不是表示Lambda表达式,需要调用Lambda方法创建一个新的表达式。如下面的代码:

static void Main(string[] args)
{
    BinaryExpression body = Expression.Add(
        Expression.Constant(2),
        Expression.Constant(3));

    Expression<Func<int>> expression = 
        Expression.Lambda<Func<int>>(body, null);

    Func<int> lambda = expression.Compile();

    Console.WriteLine(lambda());
}

访问与修改表达式目录树

在本文一开始我就说过, 通过解析表达式目录树,我们可以实现一些特定功能,既然要解析表达式目录树,对于表达式目录树的访问自然是不可避免的。在.NET Framework中,提供了一个抽象的表达式目录树访问类ExpressionVisitor,但它是一个internal的,我们不能直接访问。幸运的是,在MSDN中微软给出了ExpressionVisitor类的实现,我们可以直接拿来使用。该类是一个抽象类,微软旨在让我们在集成ExpressionVisitor的基础上,实现自己的表达式目录树访问类。现在我们来看简单的表达式目录树:

static void Main(string[] args)
{
    Expression<Func<int, int, int>> lambda = (a, b) => a + b * 2;

    Console.WriteLine(lambda.ToString());
} 

输出后为:

TerryLee_0164

现在我们想要修改表达式目录树,让它表示的Lambda表达式为(a,b)=>(a - (b * 2)),这时就需要编写自己的表达式目录树访问器,如下代码所示:

public class OperationsVisitor : ExpressionVisitor
{
    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }

    protected override Expression VisitBinary(BinaryExpression b)
    {
        if (b.NodeType == ExpressionType.Add)
        {
            Expression left = this.Visit(b.Left);
            Expression right = this.Visit(b.Right);
            return Expression.Subtract(left,right);
        }

        return base.VisitBinary(b);
    }
}

使用表达式目录树访问器来修改表达式目录树,如下代码所示:

static void Main(string[] args)
{
    Expression<Func<int, int, int>> lambda = (a, b) => a + b * 2;

    var operationsVisitor = new OperationsVisitor();
    Expression modifyExpression = operationsVisitor.Modify(lambda);

    Console.WriteLine(modifyExpression.ToString());
}

运行后可以看到输出:

TerryLee_0165

似乎我们是修改表达式目录树,其实也不全对,我们只是修改表达式目录树的一个副本而已,因为表达式目录树是不可变的,我们不能直接修改表达式目录树,看看上面的OperationsVisitor类的实现大家就知道了,在修改过程中复制了表达式目录树的节点。

为什么需要表达式目录树

通过前面的介绍,相信大家对于表达式目录树已经有些了解了,还有一个很重要的问题,就是为什么需要表达式目录树?在本文开始时,就说过通过解析表达式目录树,可以实现我们一些特定的功能,就拿LINQ to SQL为例,看下面这幅图:

TerryLee_0167

当我们在C#语言中编写一个查询表达式时,它将返回一个IQueryable类型的值,在该类型中包含了两个很重要的属性Expression和Provider,如下面的代码:

TerryLee_0168

我们编写的查询表达式,将封装为一种抽象的数据结构,这个数据结构就是表达式目录树,当我们在使用上面返回的值时,编译器将会以该值所期望的方式进行翻译,这种方式就是由Expression和Provider来决定。可以看到,这样将会非常的灵活且具有良好的可扩展性,有了表达式目录树,可以自由的编写自己的Provider,去查询我们希望的数据源。经常说LINQ为访问各种不同的数据源提供了一种统一的编程方式,其奥秘就在这里。然而需要注意的是LINQ to Objects并不需要任何特定的LINQ Provider,因为它并不翻译为表达式目录树,后面会说到这一点。

总结

本为详细介绍了表达式目录树的相关知识,为我们编写自己的LINQ Provider打下一个基础,希望对于大家有所帮助。查看目前网上的各种lINQ Provider,请访问万般皆LINQ



[新闻]中文维基百科可以访问啦
书评:硝烟中的Scrum和XP
摘要:
且看风清扬的一段话:“……你将这华山派的三四十招融合贯通,设想如何一气呵成,然后全部将它忘干净了,忘的干干净净,一招也不可留在心中。待会便以什么招数也没有的华山剑法,去跟田伯光对打”。如果有人说,既然“无招胜有招”是武学的最高境界,那干脆什么招数都不要学,拿把剑乱挥乱舞,处处破绽,也就是处处无破绽,便是天下第一了。听到这话的人肯定会笑他缺心眼。
这不是一本“是什么”的书,而是一本“如何做”的书,的确书如其名,纵观全书,没有空洞乏味的理论,只有……  阅读全文

[新闻]中文维基百科可以访问啦
个人博客两周年纪念日

       时间过的真快, 无意中发现今天是自己在博客园安家两周年的日子,于是总想写点东西来标记一下。

       在这两年当中,博客园见证了自己的成长历程。从最初朋友向自己推荐博客园并让自己成为了博客园的过客,那时自己往往只是在园子里浏览别人的文章,寻找自己所需要的信息;之后便有了在园子里安家的打算了,自从在园子里安家后,自己刚开始只是写点自己的生活锁事及心情随笔并且也不希望发表出去让别人看;接下来便慢慢对自己在工作当中觉得的比较实用的资料进行了总结,并发表出去希望能够给需要的人带来一些帮助。

       在这两年当中,发现自己的思想也有了改变,从当初只在园子里“摘菜”,转变为在园子里“种菜”,觉得人不要一味的去获取,有时候也应该想想如何去奉献。自己从园子里的高人中学到了不少知识,在此特别感谢dudu、天轰穿、李天平、鸟食轩等一大堆高人们,正是由于他们的奉献,才让自己能够花尽量少的时间,学到了尽量多的知识,相信博客园里许多朋友都会有同样的感慨吧!

       在接下来的日子里,自己将会再接再励,与博客园的朋友们一起共同进步!期待自己能够与园子里的朋友有更多的交流,相信博客园的明天会更加美好!



[新闻]中文维基百科可以访问啦
弟弟的文字。

加入了校内,看见了弟弟的文字。

和弟弟有点不一样,我思维落后了弟弟四年甚至更多,因为弟弟大学甚至可能高中就开始渐进策划他的人生了,而我在大学毕业后,走出校门,我完全不知道自己未来要做什么,能做什么,完全是一个裸体,毫无准备的,红着脸冲进社会。当我开始工作,开始羞答答的在电脑城里装机的时候,弟弟刚刚初中。面对社会,我一无所有,完全没准备没储备,残酷的生存压力下,这么多年来,我一直埋头猛冲,很少左右环顾其他,即便抬头也是远望自己的路,寻找自己的方向。于是我几乎完全不了解弟弟的初中、高中是怎么过的,更陌生的是妹妹。没有办法,自己都照顾不过来,怎么去关心别人?

有时候觉得,面对弟弟妹妹,我这个哥哥很不称职。还记得离开成都前,有一次无意在家里电脑上看见弟弟高中的一篇日记,他说:“他不是我亲哥哥。”我鼻子一酸,一下眼泪就上来了,我什么话都说不出来,只能悄悄关了电脑,离开。我能做什么呢?连自己生活都照顾不好的我,完全就是一个弱者,什么都做不了,只能恶性循环的,更亡命的工作、奋斗。后来到了杭州,弟弟在上海大二,杭州和上海便成了我往返最多的两个城市。常和妈妈通电话时,妈妈对我说弟弟的情况、心态,我就很吃醋,就是很吃醋,不给我说……

现在,我还在杭州奋斗,弟弟毕业了,带着他的储备开始工作,一登场就闪闪发光,我很骄傲,那是必然的,也很庆幸自己还没迂腐,还有抵抗的机会。今天在校内看见弟弟的一些文字,很帅很亲切,像照镜子,因为几乎所有观点都是我多年来一直坚守的。熟悉我的人会对这些文字有似曾相似的感觉,那也是必然的,流着一样的血!

《这是我的人生宣言》节选——2008-05-08 21:14
  人就活一次,我不敢有时刻忘怀,随时用这样的想法勉励自己
  我就活这么一次,不知道什么时候就会结束的生命,我到底要怎么样过才行?
  从现在算起,抛开天灾人祸,我还有大概60年好活,抛开变成糟老头的时间,我大概还有35年好奋斗,而且我已经奋斗了5年,原来,这不知不觉的感觉,就是我所有奋斗时间的八分之一
  还剩下八分之七,或者更短
  我可以接受我老的时候一贫如洗,孤身一人,露宿街头,被人唾弃,甚至坐牢,甚至卧病,我最不愿我老的时候,在某天下午,喝着茶,扇着扇子,数落着自己一生后悔的种种事情,并用此继续荼毒子女
  我还剩下35年,我就将变成一个糟老头子,到了那个时候,我非常想,无论怎么回望过去,我没有后悔的事情,我所作的一切,都是那么值得,哪怕是错,也要错的值得
  回望我这22年,我没有后悔的事情,每一步都是我自己的选择,没有违心的事情,我都按照自己的意愿来过的,哪怕遇到身不由己的情形,我也从来都没有放弃过自己
  当然,有成功也有失败,可是都无比受用
  接下来我要面临的是一个陌生的世界,我要用35年创造一个怎样的人生?
  我向往的人生是,和自己爱的人在一起,生两个孩子,有点钱过好日子,有个自己的公司,父母在,赡养,走,安葬
  我知道事情总会有变化,人生充满了未知,心想事成是童话,等待我的不只是挑战,更多的是失望与迷茫
  就像鲁豫有约里面的母亲一样,我的父母也是伟大的,我遗传了他们的独立,爸爸妈妈教我的,选择自己要的生活,过自己选择的生活,死在自己的选择里
  我妈妈经常抱怨生命不公,爸爸经常抱怨生不逢时,骂GCD,可是他们二位,用自己的言行给我和哥哥上了一课,永远无法忘怀的一课,那也是藏在了我和哥哥骨子里的东西,我们要将父母教给我们的东西,带给我们的子女,那就是,无论在什么时代,无论在什么环境下,做一个伟大的人,奋斗的人才有资格享受生命的精彩,我的路已经开始了22年,以前的种种成就了现在的我,是好,是坏,都没有关系,关键是,我依旧是我,依然坚定地走在我自己的路上
  未尝改变

《爽》——2008-05-07 19:45
今天接到一个猎头电话,挖我去一个公司做销售的LEADER
拒绝之


工资很高,每月7K,但是我不会去的
因为在我的价值观里,没有人可以用任何东西收买我
左右我的路
我会永远走在自己的路上
或者成功
或者失败
谁都无法左右我
只能看着我

我会自己选择我要的一切
不是我高傲
而是鱼说的,也是我一直想的
用一种方式活下去,无悔

我永远无悔自己的选择
而且,只有自己选择的
才会无悔

最近弟弟给我说,他在汇丰很快月薪就将破万,就在这一、两个月。我震惊,我说你太牛了,十万年薪哥哥两年前才拿到,那时28岁,你现在才刚刚毕业,就拿到了,简直是简直是。弟弟笑着拍拍我肩膀:“哥哥,你放心,我会随时给你压力的。”

我在想,如果我迂腐了,不再抗争,恐怕我无法承受这样的挑衅。所幸我没有,所幸我还能抵抗,那么,面对弟弟的挑衅,我心里的回答是:“那没办法了,当你收入月一万工资时,我要发出月一万的工资。日本人,老子要把压力扔还给你,TNND,挑衅我!‘哥哥’两个字是写着玩的么!”

为发出月一万的工资而奋斗!



[新闻]Firefox 3.1 Alpha发布 改进标签和智能地址栏
K2 BlackPoint试用(一)

今天安装好了K2 Blackpoint Beta1的虚机,安装的过程中遇到了一个小问题,K2 Blackpoint一定要安装在打了SP1补丁的WSS或者MOSS上,否则流程配置管理站点将无法访问,除此之外,安装过程十分顺利.(PS:K2 Blackpoint不能安装在没有WSS或者MOSS的环境中.)

首先,看看K2 Blackpoint长的是什么样子?

1.回归K2.NET 2003风格+Office 2007 Style的K2流程设计器,看上去还不错.设计器左边显示的是在流程可以定义的事件,大部分是与Sharepoint相关的操作,从这点可以看出K2 Blackpoint的产品定位.

 

2.Base在WSS站点上的K2 Blackpoint流程配置管理站点


下面再看看K2 Blackpoint可以做些什么?

1.Infopath Form Service + K2 Blackpoint

用了大概半个小时的时间完成了我的第一个K2 Blackpoint流程(Infopath表单事先是设计好的),整个过程没有写一行代码,很符合K2 Blackpoint的精神-"quickly - without code, without complexity.",但是Form Service必须依赖MOSS,有一定的局限性.

2.ASP.NET + K2 Blackpoint

用了整整半天的时间写了一个请假流程,流程并不复杂,主要是实现了无限动态加签的功能,虽然K2 Blackpoint不提供在流程设计器中编写自定义代码,但是还是可以实现一些复杂的实际需求的.设计思路是增加一个自身循环的Activity,在ASP.NET页面控制Activity是否跳出自身循环.

页面设计

流程设计

 

 接下来再去解决在流程设计时如何进行写数据库操作的问题?



[新闻]IBM推出代码分析工具 减少开发者错误
网站代码优化

一个网站不管大小,其实都是一套很完整的系统,从无到有都要经过设计、制作、编码、测试这几个阶段,而在这几个阶段中影响整个网站运行效率的主要是前期的数据库
设计和后期的编码阶段,下面就这两大阶段跟大家讲下,如何制作出一个相对高效的网站。
1.数据库设计
 一般来说你的数据库结构肯定是要按照给我们提要求的人来设计的,必须用到的字段是不可少的,这一点我们是无法控制的,我们能控制的可以有以下几点:
 1.数据库字段(常用的分为int,bit,datetime,decimal,nvarchar,text),
  1.数字型:一般用来记录次数分数等等,还有一种可以用在检索,排序,它比字符型来的快,如果你能用数字型的那就用数字型,特别是用来区分某条数据
  是什么类型时用,比如我们的订单是处于新建订单还是已确认还是已结,完全可以用数字1,2,3,4,5,6来表示,更重要的是如果我想看处于确认入住或
  者已结或者对账中状态的订单,如果已经是按照1,2,3,4这种顺序来区分的话那我只要查询大于某个数字的记录就可以了,而现在我们必须是按照某个字段
  等于H(已确认)或者等于D(对账中)或者等于O(已结)这在效率上明显下降很多,因为你用到了或,并且是字符型的,他是毫无规律可言的,那数据库必须把每条记录看一遍才能找到记录。
  而用大于3(比如4是已确认)的话数据库会用二分法很快就能找到记录.
  2.字符型:建议大家在用到字符型时一定要用nvarchar类型,因为实践证明用varchar等其他字符类型在存储不同编码格式的文字时会出现乱码现象(text类型除外),
  能不使用text类型就不要使用,因为text在数据库字段中他只是存储了一个指针而已,当你在查询时他首先要通过指针找具体内容然后再根据你的有求来查询,
  这在效率上已经慢人一步了,并且需要用到convert函数转换后才能进行查询,这又慢人一步,整体效率就可想而知了。
  3.日期型:主要是要注意你这个字段是需要精确到某一天还是某一天的时分秒,这主要是从数据库的整体大小考虑,数据库越大查询效率越低。
  4.添加的每个字段都要不允许为空,因为一旦为空后在查询时你会增加一个不为null的判断,这是额外的负担,而且也是可以人为避免的
  5.数据库的冗余字段,主要是用在一些统计方面,我们在数据库设计的初期虽然提要求的人没有这方面的需求,但我们必须事前做好准备,
  应该考虑到后期需要做这样的功能,尽量把统计工作分散到日常的每个简单操作中去,提高统计页面统计速度
  6.对数据库做适当的索引(索引就好像一本书的目录一样可以让你快速找到或者接近你要找的内容)
2.编码阶段
 1.网站目录的架构
  1.上传,需要把所有上传的文件都统一归到一个目录下并且设置为可写无执行权限,这样做有2个好处:
   1.可以避免浏览者上传木马等恶意程序,因为已经把执行权限关闭了
   2.如果整站需要换服务器或者多站需要共享文件的话可以很快速的做成一个虚拟目录的形式统一调用
   3.设置方便
  2.目录层次,一般在windows操作系统中如果一个目录中存放大约超过5000个文件的话,系统或者说磁盘的的寻道时间会在1-2秒或以上,这会使前台应用程序
  产生额外的等待时间,如果这时访问量很大就很容易造成阻塞现象,解决的方法是尽量分多级目录(比如按年月日等),实践证明分3级目录是最科学有效的。
 2.Sql语句
  1.Sql语句和索引的关系,必须对经常用来查询的SQL语句建立索引并保证数据库确实使用了.
  2.SQL语句必须很高效,如何实现,可以用查询分析器来分析判断,具体怎么使用和分析可以问我,这里不具体讲了.
  3.SQL语句必须做到你的页面需要用到哪些数据你才去取哪些数据,不要像.net里一样,不管3721全都给你抓出来,结果可能只使用了其中1条数据,即浪费
  带宽又浪费系统资源。
  4.Sql语句中不要出现datepart,convert等的函数,因为用这些函数表示需要数据库在计算完这些函数之后他才能返回给你数据,那这又会使前台页面产生
  额外的等待时间,解决方法是我们宁愿从数据库中多取出数据然后再在页面中使用asp内置算法去计算,这样做后我们就把应该让数据库去计算的工作分散到
  每个页面中去,浪费的只是CPU资源,而现在的CPU是完全够用的,而且可以让数据库马上释放资源迎接下一轮的查询,
  5.SQL语句中不要使用Select中再次使用select的复合语句,一是语句混乱,二是效率低下,也不要使用<>,in,not in等带有不确定因素的方法,这些都是
  导致效率低下的语句

 3.分页
  这个在asp和asp.net中已经有很好的解决方案,这里也不多讲了,自己看以前的代码就可以了
其他还有很多细节的地方,那只有在遇到时才能跟大家一起探讨。

个人主页:http://www.flash48.com/



[新闻]我国部分城市明日将现日全食(时间表)
行业网页的表单校验利器——jQuery formValidator表单校验插件
摘要: 你在做行业网页的表单校验吗?你在为密集的表单校验烦恼吗?你的表单校验需要人性化提示吗?你想在不破坏现有表单布局的情况下实现人性化提示吗?jQuery formValidator表单校验插件推出符合这种需求的校验模式。  阅读全文

[新闻]中文维基百科可以访问啦
More Posts Next page »