随笔 - 33  文章 - 0 评论 - 3 trackbacks - 0
<2010年2月>
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213

搜索

 

常用链接

我参与的团队

随笔分类(33)

随笔档案(33)

最新评论

阅读排行榜

评论排行榜

我真是OLD到死,虽然记得以前肯定看到过INTERSECT/EXCEPT这两个关键字,前不久还在羡慕Oracle有+/-集合操作符而SQL Server怎么竟然没有。。。现在想想难怪当初微软面试的时候面试官告诉我最好了解一下SQL Server 2005新的函数。。。

下面翻译一下http://www.sqlstuff.dk/post/intersect-except-versus-in-not-in.aspx,对INTERSECT/EXCEPT与IN/NOT IN进行比较。

SQL Server有两个有用的,用于找到两个表之间共有与差异行的函数:EXCEPT与INTERSECT。EXCEPT返回属于第一个表而不属于第二个表的行,而INTERSECT返回第一个和第二个表的交集。但它们的性能如何?

实际生活中我发现我很少有机会比较两个拥有完全相同数据列的表,但偶尔也会有这种需求。(难道这两个函数基本只在面试和考试中派用场。。。?)但是大多数情况下,这些行都有主键或其他索引,所以我一般自己只用IN和NOT IN。

为了测试,我建立了两个测试表:


 

DECLARE @I INT 
SET @I = 0 

WHILE @I < 10000 BEGIN 
 
IF @I % 5 <> 0 
  
INSERT INTO Table1 VALUES (@IREPLICATE('A'10)) 
 
IF @I % 4 <> 0 INSERT 
  
INTO Table2 VALUES (@IREPLICATE('A'10)) 
 
SET @I = @I + 1 
END   

我没有建立索引。
接下来我要查询属于表1不属于表2的行。由于我知道ID是一个唯一键(unique key),就只适用NOT IN。

 

SELECT * 
FROM Table1 
WHERE ID NOT IN ( 
 
SELECT ID FROM Table2 

GO 

SELECT * FROM Table1 
EXCEPT 
SELECT * FROM Table2 
GO   

 

这样是人都知道肯定NOT IN效率差的。比率差不多是23% vs. 77%,3.3倍左右。

如果我不仅需要确认ID,还需要确认VALUE,查询语句如下:


 

SELECT * 
FROM Table1 
WHERE ID NOT IN ( 
 
SELECT ID FROM Table2 

OR [Value] NOT IN ( 
 
SELECT [Value] FROM Table2 

GO 

SELECT * FROM Table1 
EXCEPT 
SELECT * FROM Table2 
GO   

差异进一步拉大。22% vs. 78%。

INTERSECT的结果也大同小异。

posted @ 2009-11-17 15:46 Dem 阅读(16) | 评论 (0)编辑

http://www.sellsbrothers.com/writing/ResourcesAndWinForms.htm

资源(A resource)是在Build期间被绑定在程序集里的命名数据。例如,你可以在你的应用程序中是用如下方式,通过载入文件系统中的图片,来设置背景图片:

public MainForm() {
  InitializeComponent();
  this.BackgroundImage = new Bitmap(@"C:\WINDOWS\Web\Wallpaper\Azul.jpg");
}

这段代码的问题当然是,不是所有的用户的Windows中都有Azul.jpg,而那些即使有的也很可能不在同一位置。即使你把图片放到你的应用程序中,一个很在意空间的用户很可能决定移出它,导致你的应用程序出现故障(这个原因好像有些扯,敢硬删应用程序文件夹内容的用户自然必须承受这个代价,虽然以前这种事情我也干过。。。)。唯一保险的方式就是确保把图片,或其他文件作为一个资源文件嵌入。你可以使用两种方式来实现。一种方式是在你的项目的Solution Explorer中右键点击,添加一个存在的项目,然后选中你想要嵌入的文件。这个文件就会被复制到你的项目的文件夹,但依然不会被嵌入。要作为资源嵌入项目,你需要右键点击文件,选择属性,在属性中找到“Embedded Resource”的选项。这样做完了之后就能够在运行时载入这个文件。很多.NET类提供了使用资源标识的构造函数,例如Bitmap:

public MainForm() {
  InitializeComponent();
  this.BackgroundImage = new Bitmap(this.GetType(), "Azul.jpg");
}

当作为一个资源被嵌入后,资源的完整名称会由项目的默认命名空间与文件名组成,例如MySecondApp.Azul.jpg。当图片在运行时被载入时,第一个参数是那个资源的类型,然后是名字的字符串。

当然,如果你直接地想在设计器看到作为背景的效果,你可以使用Property Browswer,而完全不用写载入资源的代码。例如对于背景图片,就是BackgroundImage property。这样设计器就会自动生成代码:

namespace MySecondApp {
  public class MainForm : System.Windows.Forms.Form {
  public MainForm() {
    InitializeComponent();
  }
 
  private void InitializeComponent() {
    System.Resources.ResourceManager resources =
      new System.Resources.ResourceManager(typeof(MainForm));
    ...
    this.BackgroundImage =
      (Bitmap)resources.GetObject("$this.BackgroundImage");
    ...
  }
  ...
}

在这个例子中,不是直接使用了Bitmap构造函数,而是使用了ResourceManager类。这个类可以在运行时直接访问区域性特定资源,不管资源是不是在程序集中。这样Form部署的世后就不需要改动代码或重新编译了。

另外project的Properties下默认有一个Resources.resx Resource文件。WinForm窗体默认有一个resx文件跟随。resx文件是个resource文件,即程序资源文件。
调用的时候可以这样调用:
this.BackgroundImage = global::NamespaceName.Properties.Resources.resourcename;

posted @ 2009-11-16 15:45 Dem 阅读(100) | 评论 (0)编辑
http://www.codeproject.com/KB/cs/applicationcontextsplash.aspx
http://weblogs.asp.net/justin_rogers/archive/2004/04/11/111162.aspx
 
1. 简介
 
对于开发者,我们总是想要在我们的应用程序中加入一些很酷的功能。这是我们程序员血液中无法抑制的天性本能。要不然我们早就改行做审计或销售了。对于Winform应用程序,增加酷的功能的方法之一是在应用程序启动前增加闪屏功能。
 
2. Application Context(应用程序上下文):它到底干些啥?
 
我首先花点时间说一下概念性的东西。如果了解我们的继承类在背后干了些什么会对理解有很大帮助。如果你对这些不感兴趣请跳过这章。
 
每个WinForms应用程序都有一个ApplicationContext类的实例,你可能只是不知道而已。我们来看一个WinForms的标准的Main()函数:
static void Main()
{
    Application.Run(new Form1());
}
 
你肯定看到过这个。不过你知道这个函数也能写成如下的形式?:
static void Main()
{
    ApplicationContext appCtx = new ApplicationContext(new Form1());
    Application.Run(appCtx);
}
(我试过了,的确可以)
 
在前一个例子中,Application.Run函数只是创建了一个新的ApplicationContext实例,然后把Form对象传递给它的构造函数(constructor)。在后一个例子中,我们只是手动进行了这个步骤。所以从现在开始,请记住每个WinForm应用程序有一个ApplicationContext实例,它包含着Main Form的实例。ApplicationContext的目的就是作为你应用程序的Main Form和UI线程之间的应用程序启动与终结的标识链接(notification link )。UI线程是你的应用程序用户界面所在的主线程,它负责处理应用程序的消息循环。这个消息队列接收来自操作系统的事件消息,例如鼠标右键点击,空格键被按下了,并把这些消息发送给了需要处理这些消息的Form。
 
消息循环是在ThreadContext类之中。这是一个私有的子类,定义在Application类之内。关于ThreadContext的内部机理的介绍非常少,不过你可以使用Anikrino工具(我也不知道是啥,有兴趣的google吧)来深入研究。
 
让我们返回Main函数。当Main()调用了Application.Run,它接着就会调用ThreadContext.RunMessageLoop,传递到新创建的ApplicationContext实例,而这个ApplicationContext实例中包含了应用程序的Main Form实例。然后RunMessageLoop注册了ThreadContext的回叫函数OnAppThreadExit函数在ApplicationContext的ExitThread事件后触发。这就让消息循环能得知用户什么时候关闭了应用程序的Main Form。接着RunMessageLoop把Main Form的Visible属性设置为true,这样用户就能最终看到Main Form。最后RunMessageLoop的工作就是进入真实的消息循环,开始接收和处理来自操作系统的事件消息。
(好像有点乱,我来整理一下:
Main() call Application.Run
|
/
ThreadContext.RunMessageLoop
|
/
pass in ApplicationContext instance(contain main form)
|
/
ThreadContext.RunMessageLoop call ThreadContext.OnAppThreadExit
|
/
ThreadContext.RunMessageLoop set main form visible=true
|
/
ThreadContext.RunMessageLoop start actual message loop
 
ApplicationContext类只有一个属性:MainForm。在我们之前看过的Main函数范例中,我们传入ApplicationContext构造函数的Form实例设置(get set to)了MainForm属性。set_MainForm属性会注册ApplicationContext.OnMainFormDestroy回叫函数在HandleDestroyed事件(用户关闭Form)后触发。那样ApplicationContext就知道应用程序main form什么时候被销毁。
 
这个回叫对于Windows应用程序非常重要。Forms不是应用程序,他们只是Application对象保持引用的对象。如果Application对象不知道什么时候main form被销毁,那么它会永无止境地运行消息循环。因此当用户关闭了main form,form会发起它自己的HandleDestroyed事件,而这个事件会调用ApplicationContext的OnMainFormDestroy回叫函数。这个回叫函数接着发起ThreadContext的ExitThread事件,调用ThreadContext的OnAppThreadExit回叫函数。而调用这个函数告诉ThreadContext应用程序的main form已经被销毁,它可以终结UI线程了。最后把应用程序的关闭消息返回给操作系统,清空所有资源,终结UI线程。(过程真纠结。。。。)
 
3. 根据上面的概念来创建一个闪屏
 
上面有些说得太多了,不过这有助于你来理解接下来我们究竟要做些什么。
 
微软本可以不暴露出ApplicationContext类来给我们使用,但他们最终还是暴露了出来。因此我们能继承然后自定义这个启动过程。本文中我们就会创造一个自定义的ApplicationContext,包括两个Form,一个闪屏Form,一个main form。
  

另外新建一个Class SplashAppContext.cs,这个SplashAppContext类继承ApplicationContext类。
ApplicationContext有两个构造函数ApplicationContext()与ApplicationContext(Form),后者在初始一个新的ApplicationContext实例的同时还会附带一个指定的Form。如果使用了这个构造函数,可能需要重载OnMainFormClosed函数,不然线程的消息循环会在MainForm关闭时随之关闭。

代码如下:

 

    class SplashAppContext:ApplicationContext
    {
        Form mainForm 
= null;
        Timer splashTimer 
= new Timer();

        
public SplashAppContext(Form mainForm, Form splashForm)
            : 
base(splashForm)
        {
            
this.mainForm = mainForm;
            splashTimer.Tick 
+= new EventHandler(splashTimer_Tick);
            splashTimer.Interval 
= 10000;
            splashTimer.Enabled 
= true;
        }

        
void splashTimer_Tick(object sender, EventArgs e)
        {
            splashTimer.Enabled 
= false;
            splashTimer.Dispose();

            
base.MainForm.Close();
        }

        
protected override void OnMainFormClosed(object sender, EventArgs e)
        {
            
if (sender is Splash)
            {
                
base.MainForm = this.mainForm;
                
base.MainForm.Show();
            }
            
else if (sender is Main) 
            {
                
base.OnMainFormClosed(sender, e);
            }
        }
    }

 

之前提到过的Timer的知识就是应用在这个上面的,回忆不起来用法的可以参考http://www.cnblogs.com/galaxyyao/archive/2009/10/04/1577860.html。关于
public SplashAppContext(Form mainForm, Form splashForm)
            : base(splashForm)
这段,感谢renyu同学的解释。它会先运行父类的方法再运行子类的方法。因为是base(splashForm),所以会先创建一个splashForm,开启计时器splashTimer,然后创建一个mainForm。
少女计时中。。。(这是一个neta,请54)
当计时器到点,触发base.MainForm.Close(),但由于OnMainFormClosed被重载过,所以在关闭时还会检查一下是不是splashForm。如果是splashForm的话,换最终要显示的mainForm显示,然后splashForm自己dispose销毁。
最后我们打开包含Main函数的Program.cs,把Application.Run(new Main());替换成自定义的ApplicationContext:

 

SplashAppContext splashContext = new SplashAppContext(new Main(), new Splash());
Application.Run(splashContext);

 

这样,一个简单的闪屏程序就完成了。


posted @ 2009-10-28 19:36 Dem 阅读(74) | 评论 (0)编辑

http://www.hanselman.com/blog/PermaLink.aspx?guid=af453d70-64b3-417e-9492-d115f929195d
http://msdn.microsoft.com/zh-cn/library/cc656912.aspx

关于.NET的大小经常有一些误解。.NET Framework并不真的需要下载200+M大小的安装包。

1. 我使用的是什么样的安装包?
用最简单的方式描述:
a. 离线安装包
-一个可以离线运行的单独文件。它是完整的,适用于所有平台,可离线安装的。
b. 在线安装包
-一个2.7M安装程序(名为“bootstrapper”)。它会检测你需要哪些文件,下载10-60M。
注意:如果你是一个办公室IT人员,你可能需要决定你是想要办公室里的每个人分别下载.NET,还是一次性下载完,放在一个网络共享上供他人运行。你可以阅读“Deployment Guide for Administrators”<http://msdn.microsoft.com/en-us/library/cc160717.aspx>判断是否要通过AD或SMS来推送。

2. 那么我到底需要下载多大?
这取决于你已经安装的版本。如下是一个XP SP2机器上的试验结果:
.NET版本          升级到3.5 SP1需要下载的大小        下载时间(512Kbps)
无                   约56MB                                     15分钟
2.0                 约50MB                                     15分钟
2.0 SP1           约33MB                                     9分钟
3.0 SP1           约10MB                                     3分钟

从下载的观点来看,这些数字不算太坏,并不如很多人通常描述的那样。我不是为微软辩护,也不是微软的五毛党,我只是显示我从我的测试看到的数据。我的一切观点基于数据。

但是,作为一个自由的小独立开发者,和一个.NET客户端应用程序的分发者(有兴趣的可以访问原作者的网站:http://www.hanselman.com/babysmash/),我总是希望下载的大小越小越好。我经常收到如下的邮件:“我很喜欢你们的软件,但我不想下载200M的.NET Framework。”你们中很多人肯定也收到过类似的邮件。要想改变,最好的方式就是增加“实质性部分”。

3. 在线体验
“客户端配置文件(Client Profile)”是什么?
客户端配置文件<http://www.microsoft.com/downloads/details.aspx?FamilyId=8CEA6CD1-15BC-4664-B27D-8CEBA808B28B&displaylang=en>是一个在XP上安装.NET 3.5 SP1的选择。它只有277k。(下载页面上的介绍:.NET Framework客户端配置文件在线安装包包含了在线安装和分发所需的.NET Framework的程序集)

当它在一台不带任何.NET Framework的Windows XP SP2机器上运行时,它会下载一个28M的有效负载,给你一个对应于特定客户端的.NET 3.5的子集。(似乎意思就是可以减少28M的下载量?)如果客户端配置文件运行在已安装任何版本的.NET的机器上,那么它就会采取和3.5 SP1在线安装相同的行动,检测需要下载的量并去下载。更详细请参考"Client Profile Deployment Guide"<http://download.microsoft.com/download/5/a/a/5aa86d6c-969b-42d8-bc6b-30e02bfeccf0/NETFXClientProfile_DeploymentGuide.htm>和http://msdn.microsoft.com/zh-cn/library/cc656912.aspx。(不过看完后我发现这玩意似乎只对XP有用。。。Vista上面还是要完全安装,由于默认自带3.0。)

有人提到的.NET Framework安装包过大需要200+M(如http://blog.deploymentengineering.com/2008/08/net-35-sp1-231mb.html),这指的是离线安装包。

4. 离线体验
虽然默认的离线安装包很大,你也可以修改这个离线安装包,使之尽量得小。如果你只支持x86平台,那么就可以只需要x86的部分。"How to create an installable layout for the final release of the .NET Framework 3.5"<http://blogs.msdn.com/astebner/archive/2007/12/03/6646794.aspx>一文中描述了具体如何精简。在更高的层面上,还可以根据检测支持的操作系统和处理器架构,然后选择性地移除。

这主要是针对于管理员和IT人员的。还有更牛的人可以采用分离,压缩或其他方法让安装包更加小。

原作者还制作了这个网站:
http://www.smallestdotnet.com/
通过嗅探你的浏览器用户代理,告诉你你现在的.NET版本,你需要下载多大,哪种分发包最适合于你。这个网站也包含了一些Javascript,你可以加入你的产品网站,例如:
<script src="http://www.smallestdotnet.com/smallestdotnet/javascript.ashx" type="text/javascript"></script>

Detected 3.5 SP1 .NET Framework. No update needed.

posted @ 2009-10-21 18:29 Dem 阅读(72) | 评论 (0)编辑

http://www.go4expert.com/forums/showthread.php?t=2122

System.Windows.Forms.Timer
1. 它是一个基于Form的计时器
2. 创建之后,你可以使用Interval设置Tick之间的跨度,用委托(delegate)hook Tick事件
3. 调用Start和Stop方法,开始和停止
4. 完全基于UI线程,因此部分UI相关的操作会在这个计时器内进行
5. 长时间的UI操作可能导致部分Tick丢失

System.Timers.Timer
1. 用的不是Tick事件,而是Elapsed事件
2. 和System.Windows.Forms.Timer一样,用Start和Stop方法
3. AutoReset属性决定计时器是不是要发起一次事件然后停止,还是进入开始/等待的循环。System.Windows.Forms.Timer没有这个属性
4. 设置对于UI控件的同步对象(synchronizing object),对控件的UI线程发起事件


这两者与System.Threading.Timer的区别比较见http://mark.michaelis.net/Blog/SystemWindowsFormsTimerVsSystemThreadingTimerVsSystemTimersTimer.aspx,这里只摘录最后的总结:
System.Windows.Forms.Timer是对于用户界面编程的比较显然的选择。而另外两个之间的选择就不是很明显。如果必须在IContainer内,那么就应该选择System.Timers.Timer。如果没有用到System.Timers.Timer的特性,那么建议选择System.Threading.Timer,因为它稍稍轻量级一些。

posted @ 2009-10-04 02:10 Dem 阅读(84) | 评论 (0)编辑
     摘要: 基于http://msdn.microsoft.com/en-us/magazine/cc163672.aspx与MSDN你强烈地希望把你的应用程序的闪屏加上令人激动的“Funky Cold Medina”(为了让你们之中不是80后的人听懂,我解释一下这是Tone Loc的歌)。在Visual Studio 2005之前,即使在你的应用程序中加入最简单的曲调和系统声音也是一...  阅读全文
posted @ 2009-10-02 19:20 Dem 阅读(46) | 评论 (0)编辑
     摘要: 如果是Linux客户端连SQL Server。。。其实最好的方法就是不用SQL Server当数据库。。。推荐MySQL。但万一真的有需求要用怎么办?第一建议是使用SUSE Linux。毕竟有过协议,SUSE Linux有微软官方的支持何推荐,使用SQL Server JDBC Driver。The Microsoft SQL Server JDBC Driver is designed to w...  阅读全文
posted @ 2009-09-24 16:44 Dem 阅读(52) | 评论 (0)编辑
     摘要: http://blogs.msdn.com/psssql/archive/2009/09/11/fun-with-locked-pages-awe-task-manager-and-the-working-set.aspx我知道关于“Locked Pages”,AWE的话题会非常令人困惑。任何人被这个搞晕头我都会认为非常正常。但我也知道我们已经无数遍地发博客和讨论过这个话题...  阅读全文
posted @ 2009-09-24 14:25 Dem 阅读(77) | 评论 (0)编辑
     摘要: 首先要说明两个概念:1. Windows Security Center这个东西的概念似乎是从Vista开始的。反正就是整合了防火墙,系统更新,防毒软件等等的综合平台。2. Windows 管理规范(Windows Management Instrumentation)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。WMI 通过编程和脚本语言为日常管理提供了一条...  阅读全文
posted @ 2009-09-16 00:21 Dem 阅读(48) | 评论 (0)编辑
     摘要: System.Diagnostics命名空间中的一个类。其实就相当于一个秒表。可以不止停一次。Start方法是按下秒表开始计时,Stop方法是再次按下秒表暂停计时,IsRunning属性来判断秒表是否在运行,Reset方法将秒表清零。它的机制如下:如果已安装的硬件或操作系统提供了高分辨率(high-resolution)的计数器,就用那个计数器;不然就系统计时器。Frequency和IsHighR...  阅读全文
posted @ 2009-09-14 14:05 Dem 阅读(43) | 评论 (0)编辑