posts - 18,  comments - 57,  trackbacks - 3
  2008年7月5日
以动手实践为荣 , 以只看不练为耻;
以打印日志为荣 , 以单步跟踪为耻;
以空格缩进为荣 , 以制表缩进为耻;
以单元测试为荣 , 以人工测试为耻;

以模块复用为荣 , 以复制粘贴为耻;
以多态应用为荣 , 以分支判断为耻;
以Pythonic为荣 , 以冗余拖沓为耻;
以总结分享为荣 , 以跪求其解为耻;
posted @ 2008-07-05 18:43 山伟 阅读(27) | 评论 (0)编辑
  2006年2月22日
同一个局域网内A、B、C三台机器,均安装.net 1.1和2.0
其中A安装有SQL Server 2K,B和C都没有安装SQL Server 2K,但C安装有SQL Server 2005 Express
同样的程序,.net 1.1编译后在A、B、C运行都能访问A机器的SQL Server 2K
.net 2.0编译后,在A中能访问SQL Server 2K,在B中不能,C中却可以
请问哪位大侠遇到过这种情况?该怎么做才能使B中的程序也能访问A的SQL Server 2K

2006-2-23:
刚做完测试,问题解决了,是端口问题,狂郁闷啊!
想当年学Oracle的时候客户端也总是连不上服务器,郁闷了好几天最后把防火墙关掉就好使了,类似的问题这次却没想到。
不过还是有些不明白为什么1.1编译的程序为什么可以在不打开端口的情况下访问数据库。
posted @ 2006-02-22 13:19 山伟 阅读(244) | 评论 (2)编辑
  2006年1月1日
      好久没在园子里发过帖子了,2006年的第一天本该回首05年的点滴、展望未来的,无奈总结从圣诞夜就开始写到现在都没写完。 
      最近在看Bill Wagner的《Effectie C#》,本来想把书中提到的50条提高效率的方法逐一翻译出来也写成一系列博客,后来在MSDN看到李建忠的《Effective C#》 翻译札记,知道他在翻译这本书,于是我也就不再献丑了,只写一些体会吧。

      Item 1: Always Use Properties Instand of Accessbile Data Members
      Item 2: Prefer readonly to const

      关于第一条李建忠已经有很好的说明了,但我在这里想说的却是如果一开始用一个public字段而以后发现有必要改成属性的时候带来的麻烦。
      Effective C#更多的是以大型的组件式的开发为讨论基础的,所以往往是很多模块的,你在一个DLL里定义的public字段如果改成属性,那么所有使用这个DLL的模块都得重新编译一次才行(public字段和属性编译成IL后的代码就不再贴出来了,有兴趣的朋友可以自己尝试一下),而如果一开始就使用属性,那么只要重新编译一次修改的DLL就可以了。孰优孰劣,不同的情景要进行不同的权衡。
      关于第二条,就会提到一件令我汗颜很久的事。学C那会儿,声明一个常量数组是很方便的,到C#后发现用private const int[] m=new int[] {10, 20, 30};是编译不过去的,后来想想也就明白为什么了,因为数组是按引用类型处理的,而const却只能用在一些简单类型上,比如int、float、enums、string等简单数据上,引用类型是不行的。但怎么去声明一个只读的数组我却很久没有解决,直到看了Effective C#,也很简单的,就是用readonly来做(汗颜啊)。
      这里要说的也和第一条类似,在一个DLL里定义一个类:
1public class UsefulValues
2{
3    public static readonly int StartValue = 5;
4    public const int EndValue = 10;
5}
     然后在另一个程序集里去使用这些数据:
1for(int i = UsefulValues.StartValue; i < UsefulValues.EndValue; i++)
2    Console.WriteLine("value is {0}", i);
得到的结果是
      value is 5
      value is 6
      ……
      value is 9

      好,现在把UsefulValues里的数据改一下,StartValue=105,EndValue = 120,然后重新编译这个DLL,然后再运行一下第二个程序集,你希望的结果是
      value is 105
      value is 106
      ……
      value is 119
      但结果呢,你什么输出也没得到。还是看IL代码,会发现在第二个程序集里EndValue是被替换成10了,这是编译时的行为,而如果用readonly来定义的只读值却是在运行时才确定是哪个值的。

      Effective C#很多时候都考虑到发生改变的情况,正如李建忠所说,如果是一个“一次编写、N年都run”的项目,这些规则其实并不是一定要遵守的。还是那句话,权衡很重要。
posted @ 2006-01-01 12:10 山伟 阅读(570) | 评论 (1)编辑
  2005年11月18日
    现在手头做的工作是给一家公司做奖金结算系统,之前也是有个程序员做的(我也纳闷儿,怎么现在做的都是别人失败了才让我做),在用他的程序计算了两个月左右的时候发现总出计算错误,然后这家公司让我做。用我的计算了这么长时间了,也没出过什么问题,前天忽然说因为前面的出错的已经都发出去了,和现在数据库里的数据不一致,要把数据库里的数据改过来(现在终于明白了什么情况下错的也要当成正确的)。我一看不能让用我程序的文员直接修改数据库啊,再写短程序也没必要,我就让他们把数据整理好后我来修改,结果一天没和我联系。昨天早上发给我了,我一看傻了,21个Excel文档!
     一开始我就打开SQL Server企业管理器,用SQL语句读出一个Excel文档记录的数据,然后开始修改,当改到第四个时,发现弄串了把第四个的数据改到第三个了。这个时候,我又看了看Excel文档,忽然想到用宏能不能解决呢。
     因为更改数据库主要就是需要三列数据,选择Excel的三列复制到文本文件,每列之间是用制表符分开的,用宏也没办法把每一行数据做成SQL语句,无奈之下只好复制作为查询的那一列,然后用宏组建成一条SQL查询语句,这样最起码不用再一个一个的查找了。弄了一天好不容易弄完。一边弄一边还告诫自己:抓紧时间学习一下代码生成的东西,以后就不用这么累了。
     今天早上睡梦中忽然想到一个办法,惊醒,然后开机尝试,成功了!
     是这么做的:
     用SQL Server把Excel中那三列导到一个表里,然后再导出到文本文件,列与列之间用分号分隔,这样就得到下面这种格式的数据:
     0;1995;'lxh'
     100;0;'1992'
     1500;15;'519'
     50;12;'337'
     好了,用VS.NET打开这个文本文件,把光标放在第一行开始记录宏,然后输入:update bonus set teambonus=,然后查找';',这时0后面的分号被选中,接着输入:,managebonus=,然后再查找分号,接着输入一个空格,然后是where memberid=,然后把光标移到下一行,停止记录宏。
这时候第一行就变成了update bonus set teambonus=0,managebonus=1995 where memberid='lxh'。好了,剩下的就是对着这个宏开始疯狂的点击了

     昨天没有实现其实就是因为直接从Excel表格复制到文本文件,这样在宏记录的时候,无法判断三个数据之间的分隔符,也就无法组建新的SQL语句了。
posted @ 2005-11-18 07:08 山伟 阅读(314) | 评论 (2)编辑
  2005年11月2日
     摘要: 因为要给师弟们讲课,我写了异型窗体制作(两种方法) 这篇博客。后来有个师弟说他把我的代码修改成了一个组件,想把这个组件拖拽到窗体里,经过简单设置就能实现不规则窗体,但是没有成功。经过实验,我这里重新把原来的代码整理了一下,下面这个组件CusomForm编译后就可以使用,拖拽到窗体后需要设置ParentForm、BackImage、TranTransparentColor三个属性,并且不用再写代码处... 阅读全文
posted @ 2005-11-02 13:04 山伟 阅读(1043) | 评论 (4)编辑
  2005年11月1日

有memberinfo和updatelog两个表,通过memberinfo的memberid和updatelog的memberid对两个表进行关联,memberinfo纪录会员基本信息,updatelog纪录会员的升级信息。
memberinfo数据如下
memberid   star
001           1
002           1
003           2

updatelog数据如下
memberid  endstar   updatetime
001           2           2005-5-24
001           3           2005-5-28
001           5           2005-6-9
002           4           2005-5-29

想得到的数据为
会员号   星级
001          5
002          4
003          2

最初我是通过C#读取两个表的数据,然后一一对应组成一个新表,这样执行效率是非常低的,而且代码还非常多。就想通过SQL语句查询得到,在csdn上发帖子也没人解答。问一个师兄(他毕业后一直是Oracle数据库管理员),他说他做不了,给我写了个存储过程,因为他用到了游标,我也没看明白。昨天弄了一上午终于弄出来了,其实很简单的:

 1SELECT memberid AS 会员号, CASE WHEN
 2          ((SELECT TOP 1 endstar
 3          FROM updatelog
 4          WHERE memberinfo.memberid = updatelog.memberid
 5          ORDER BY updatetime DESCIS NULLTHEN memberinfo.star ELSE
 6          (SELECT TOP 1 endstar
 7         FROM updatelog
 8         WHERE memberinfo.memberid = updatelog.memberid
 9         ORDER BY updatetime DESCEND AS 星级
10FROM dbo.memberinfo

不过(SELECT TOP 1 endstar FROM updatelog WHERE memberinfo.memberid = updatelog.memberid  ORDER BY updatetime DESC)这一句执行两次,肯定会消耗资源的,不知道有没有更好的解决方法。

最近的体会就是我写的程序很少能体现的出数据库管理系统的性能(都是用程序读取数据出来然后再自己去组合数据),所以我从不敢说Oracle和SQL Server到底哪个好。这个东西用SQL写出来后,代码比以前少很多,可读性也更强了。数据库程序员还是好好学学怎么写SQL语句吧,这个能提升做的系统的性能。


2006-4-3
今天看到Ember 给我的留言,然后就又看到这篇博客,这里会造成SQL语句那么长,其实是数据库设计不好的原因,如果数据库设计合理,完全不会造成查询的困难。
另外看到这个SQL语句,想到了可以简化的方法,就是使用ISNULL这个函数

1SELECT memberid AS 会员号, ISNULL
2          ((SELECT MAX(endstar)
3          FROM updatelog
4          WHERE memberinfo.memberid = updatelog.memberid), star) AS 星级
5FROM memberinfo

 

posted @ 2005-11-01 12:56 山伟 阅读(377) | 评论 (7)编辑
  2005年10月24日
        因为要做一个类似Windows Update的东西,以免程序更新时跑来跑去麻烦,虽然类似的工具很多,但是大都很复杂,于是决定自己做一个类似的简单程序。
        对比客户端和服务器端的程序版本,并把服务器端新版本程序拷回来都好做(用VPN,相当于局域网内文件复制),但是安装新版本程序就有问题了,因为Windows Installer安装程序时如果发现有以前的版本就会要求你自己删除旧版程序后再重新安装,但我要实现的是自动卸载并安装。直接运行msi文件出错,那我就穿参数,因为没有找到相关资料就猜卸载应该是/u,运行的时候没有卸载来反倒是弹出来一个对话框,里面有Windows Installer的参数设置介绍:
Windows (R) Installer. V 3.01.4000.1830 

msiexec /Option <Required Parameter> 
[Optional Parameter]

安装选项
    </package | /i> <Product.msi>
        安装或配置产品
    /a <Product.msi>
        管理安装 - 在网络上安装产品
    /j<u|m> <Product.msi> 
[/t <Transform List>] [/g <Language ID>]
        播发产品 - m 播发到所有用户,u 播发到当前用户
    </uninstall | /x> <Product.msi | ProductCode>
        卸载产品
显示选项
    /quiet
        安静模式,无用户交互
    /passive
        无从参与模式 - 只显示进程栏
    /q
[n|b|r|f]
        设置用户界面级别
        n - 无用户界面
        b - 基本界面
        r - 精简界面
        f - 完整界面(默认值)
    /help
        帮助信息
重新启动选项
    /norestart
        安装完成后不重新启动
    /promptrestart
        提示用户重新启动(如果必要)
    /forcerestart
        安装后总是重新启动计算机
日志选项
    /l
[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>
        i - 状态消息
        w - 非致命警告
        e - 全部错误消息
        a - 操作的启动
        r - 操作特定记录
        u - 用户请求
        c - 初始界面参数
        m - 内存不足或致命退出信息
        o - 磁盘空间不足消息
        p - 终端属性
        v - 详细输出
        x - 额外调试信息
        + - 扩展到现有日志文件
        ! - 每一行刷新到日志
        * - 记录所有信息,除了 v 和 x 选项
    /log <LogFile>
        与 /l* <LogFile> 相同
更新选项
    /update <Update1.msp>
[;Update2.msp]
        应用更新
    /uninstall <PatchCodeGuid>
[;Update2.msp] /package <Product.msi | ProductCode>
        删除产品的更新
修复选项
    /f
[p|e|c|m|s|o|d|a|u|v] <Product.msi | ProductCode>
        修复产品
        p - 仅当文件丢失时
        o - 如果文件丢失或安装了更旧的版本(默认值)
        e - 如果文件丢失或安装了相同或更旧的版本
        d - 如果文件丢失或安装了不同版本
        c - 如果文件丢失或较验和与计算的值不匹配
        a - 强制重新安装所有文件
        u - 所有必要的用户特定注册表项(默认值)
        m - 所有必要的计算机特定注册表项(默认值)
        s - 所有现有的快键方式(默认值)
        v - 从源运行并缓存本地数据包
设置公共属性
    
[PROPERTY=PropertyValue]

请查阅 Windows (R) Installer SDK 获得有关
命令行语法的其他文档。

版权所有 (C) Microsoft Corporation. 保留所有权利。
此软件的部分内容系基于 Independent JPEG Group 的工作。
       按这个传参数试了好多次(我比较笨),终于成功了。下面把代码贴出来,要安装的程序名是Clock.msi
using System;
using System.Diagnostics;

public class mainTest
{
    
public static void Main()
    
{
        
// Windows Installer的命令为msiexec
        ProcessStartInfo startInfo = new ProcessStartInfo("msiexec");
        
// 卸载程序的参数
        startInfo.Arguments = string.Format("/uninstall Clock.msi");
        Process p 
= new Process();
        p.StartInfo 
= startInfo;
        p.Start();
        p.WaitForExit();
        
// 安装程序的参数
        startInfo.Arguments = string.Format("/i Clock.msi");
        p.Start();
        p.WaitForExit();

        
if (p.HasExited) 
        
{
            
// 安装完毕启动新安装的程序
            startInfo = new ProcessStartInfo(@"C:\Program Files\Spider\Clock\Clock.exe");
            p.StartInfo 
= startInfo;
            p.Start();
        }

    }

}
posted @ 2005-10-24 21:44 山伟 阅读(1134) | 评论 (1)编辑
  2005年10月19日
     摘要: 异型窗体制作可以说在网上一找就一堆,以下这些代码也算是对我以前写程序的一个总结吧。记得这段代码我是在看了Windows C制作异型窗体的原理后写出来的。主要就是传一个Form的对象和一个Bitmap对象给SetWindowRegion方法,SetWindowRegion方法就会完成设置。传的图片要有一个透明色,如果没有设置透明色,就会以图片(0,0)像素的颜色为透明色。具体的实现过程就是扫描图片的... 阅读全文
posted @ 2005-10-19 21:12 山伟 阅读(550) | 评论 (1)编辑
  2005年10月9日
      刚写程序那会儿喜欢用SqlCommand直接操作数据库,因为感觉这样所作的修改可以马上体现到数据库中去,最近做的东西是一个奖金结算系统,每一个人的奖金都和其他人有关,如果用SqlCommand就得频繁的操作数据库,于是我就用数据集把数据全部读取出来,然后计算,计算完毕再把结果写回数据库。如果不是今天早上的事,我想我也不会去进一步去想,也不会觉得这么做有问题。
      前天写一个把大量数据写入数据库的程序。这个数据库有两个表,一个放置着原始数据,一个是程序要往里写的目标数据表。原始数据有17个字段,要把这17个字段进行组合(所有组合的情况,有131071种情况),然后每种组合情况里要把组合的字段里所有的数据再合并成一个大的字符串写入数据。数据量是相当惊人的。开始时我用数据集做的,把计算的数据放到一个数据表里,然后用数据适配器回传数据给数据库。结果内存一路飘升,最后告诉我内存溢出。然后我就开始看垃圾回收之类的内容。该回收的也回收了,该溢出的地方还是溢出,但自始至终我都没认为是DataTable的原因。后来实在没办法了就用SqlCommand一条一条的写数据,用了四个线程同时写,写了近一个小时(在服务器上跑的),最后结果让我大吃一惊:数据库文件(包含日志文件)将近50G!这个时候我才意识到可能是DataTable的问题,又写了段代码测试,果然,用SqlDataAdapter的Fill方法往数据集里写数据时CPU使用率和内存使用量都是一路飘升!最后弹个框告诉我不可预知的错误,关掉框控制台就显示内存溢出!
      不明白了,那什么时候使用数据集?那个奖金结算系统必须得把每个人的数据都读取出来才能计算,那么数据量巨大的时候岂不是只有崩溃?
      请大侠们明示。
posted @ 2005-10-09 18:12 山伟 阅读(463) | 评论 (5)编辑
  2005年10月8日
     摘要: 原文地址 源码下载 简介 这个程序在内存中动态编译代码片段并且运行它,所以你在测试C#或VB.NET代码时不必再创建新的工程或解决方案了。 背景 通常我们需要测试一些代码片段(C#或VB.NET),在.NET环境中,我们用"CSC"或"VBC"命令;在VS.NET中,我们创建新的工程或解决方案,并且创建很多其他文件。这两种方法都是沉闷乏味的,特别是当我们测试一个很简单的程序时。jconwell创作... 阅读全文
posted @ 2005-10-08 22:05 山伟 阅读(846) | 评论 (1)编辑
<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

与我联系

搜索

 

常用链接

留言簿

我参与的团队

随笔分类(18)

随笔档案(18)

文章分类(2)

文章档案(2)

相册

收藏夹(102)

程序专业网站

出版社\作者

开源软件

朋友博客

最新评论

阅读排行榜

评论排行榜