2009年1月31日星期六

德国研究人员发现苹果汁能抑制健忘

新华网柏林1月26日电德国研究人员的实验发现,每天喝两杯苹果汁可以帮助大脑减少造成阿耳茨海默氏症(早老性痴呆症)患者逐渐丧失记忆的β-淀粉蛋白的堆积,从而抑制健忘。


据德国《焦点》周刊网站日前报道,美国马萨诸塞大学研究人员托马斯·谢伊及其研究小组在实验中发现,饮用了苹果汁的老鼠,其病理性的健忘症有缓慢好转。当老鼠每天饮用相对于人每天喝两杯的量时,这种效果就显现出来。实验发现,仅1个月之后,老鼠大脑内β-淀粉蛋白的堆积就已减少。


托马斯·谢伊说:“这一结果是饮食与老年性神经退化存在联系的另一个证明。显然,均衡的饮食不仅能支持大脑最佳地发挥作用,还能延迟阿耳茨海默氏症的发作。”


研究人员发现,苹果汁能促进神经递质乙酰胆碱的产生,其结果是记忆力增强。神经递质是将信息从一个神经细胞传送到另一个神经细胞的化学传递物质。

常吃西红柿可治疗十种病

西红柿是一种很普通的食物,但在治疗疾病等方面却有着举足轻重的作用,下面列举十种治疗功效,供朋友们参考。
1、治皮肤病
将鲜熟西红柿去皮和籽捣烂敷患处,每日2—3次,可治真菌、感染性皮肤病。
2、美容防衰老
将鲜熟西红柿捣烂取汁加少许白糖,每天用其涂面,能使皮肤细腻光滑,美容防衰老效果极佳。
3、防癌
因西红柿不仅营养丰富,且具有较强的清热解毒、抑制病变功效,坚持每天吃1—2个鲜熟西红柿,可起到防癌和辅助治疗癌症的作用。
4、治高血压
每天早晨选1—2个鲜熟西红柿空腹蘸白糖吃,降血压效果明显。
5、治贫血
将西红柿、苹果各一个,芝麻15克,一次吃完。每日吃1—2次长期坚持,可治贫血。
6、治溃疡
轻度消化性溃疡患者,可将榨取的西红柿和马铃薯汁各半杯混合后饮用,每天早晚各一次,连服10次,溃疡可愈。
7、治肝炎
取西红柿丁一匙,芹菜末、胡萝卜末、猪油各半匙伴入沸米粥内烫熟,加入盐、味精适量食用,对治疗肝炎效果极佳。
8、防中暑
将1-2个西红柿切片,加盐或糖少许,熬汤热饮,可防中暑。
9、退高烧
将西红柿汁和西瓜汁各半杯混合饮用。每小时一次,可退高烧。
10、治牙龈出血
将西红柿洗净当水果吃,连吃半月,即可治愈牙龈出血。

常吃西红柿可治疗十种病

西红柿是一种很普通的食物,但在治疗疾病等方面却有着举足轻重的作用,下面列举十种治疗功效,供朋友们参考。
1、治皮肤病
将鲜熟西红柿去皮和籽捣烂敷患处,每日2—3次,可治真菌、感染性皮肤病。
2、美容防衰老
将鲜熟西红柿捣烂取汁加少许白糖,每天用其涂面,能使皮肤细腻光滑,美容防衰老效果极佳。
3、防癌
因西红柿不仅营养丰富,且具有较强的清热解毒、抑制病变功效,坚持每天吃1—2个鲜熟西红柿,可起到防癌和辅助治疗癌症的作用。
4、治高血压
每天早晨选1—2个鲜熟西红柿空腹蘸白糖吃,降血压效果明显。
5、治贫血
将西红柿、苹果各一个,芝麻15克,一次吃完。每日吃1—2次长期坚持,可治贫血。
6、治溃疡
轻度消化性溃疡患者,可将榨取的西红柿和马铃薯汁各半杯混合后饮用,每天早晚各一次,连服10次,溃疡可愈。
7、治肝炎
取西红柿丁一匙,芹菜末、胡萝卜末、猪油各半匙伴入沸米粥内烫熟,加入盐、味精适量食用,对治疗肝炎效果极佳。
8、防中暑
将1-2个西红柿切片,加盐或糖少许,熬汤热饮,可防中暑。
9、退高烧
将西红柿汁和西瓜汁各半杯混合饮用。每小时一次,可退高烧。
10、治牙龈出血
将西红柿洗净当水果吃,连吃半月,即可治愈牙龈出血。

2009年1月30日星期五

如何互相同步两个相同的sql数据库

以下实现复制步骤(以快照复制为例)

运行平台SQL SERVER 2005

一、准备工作:

1.建立一个 WINDOWS 用户,设置为管理员权限,并设置密码,作为发布快照文件的有效访问用户。

2.在SQL SERVER下实现发布服务器和订阅服务器的通信正常(即可以互访)。打开1433端口,在防火墙中设特例

3.在发布服务器上建立一个共享目录,作为发布快照文件的存放目录。例如:在D盘根目录下建文件夹名为SqlCopy

4.设置SQL 代理(发布服务器和订阅服务器均设置)本篇文章发表于www.xker.com(小新技术网)

打开服务(控制面板---管理工具---服务)

---右击SQLSERVER AGENT---属性---登录---选择“此帐户“

---输入或选择第一步中创建的WINDOWS 用户

---“密码“中输入该用户密码

5.设置SQL SERVER 身份验证,解决连接时的权限问题(发布、订阅服务器均设置)

步骤为:对象资源管理器----右击SQL实例-----属性----安全性----服务器身份验证------选“SQL Server和WINDOWS“,然后点确定

6.开启SQL Server 2005的网络协议TCP/IP和管道命名协议并重启网络服务。

7.在SQL Server中创建步骤1中对应的系统用户登陆名,作为发布数据库的拥有者(设置为dbo_owner和public)。

8.以系统超级用户sa登陆SQL Server建立数据库和表。

9.发布服务器和订阅服务器互相注册

步骤如下:视图----单击以注册服务器----右键数据库引擎----新建服务器注册-----填写要注册的远程服务器名称------身份验证选“SQL Server验证“-----用户名(sa) 密码------创建组(也可不建)-----完成。

10.对于只能用IP,不能用计算机名的,为其注册服务器别名

二、开始:

发布服务器配置(在发布服务器上配置发布和订阅)

1. 选择 复制 节点

2. 右键本地发布 ----下一步---------系统弹出对话框看提示----直到“指定快照文件夹“

----在“快照文件夹“中输入准备工作中创建的目录(指向步骤3所建的共享文件夹)------选择发布数据库-------选择发布类型-------选择订阅服务器类型-------选择要发布的对象------设置快照代理-------填写发布名称。本篇文章发表于www.xker.com(小新技术网)

3. 右键本地订阅--------选择发布服务器-------选择订阅方式(如果是在服务器方订阅的话选择推送订阅反之

选择请求订阅)-------填加订阅服务器--------选择代理计划(一般选择连续运行)---------其余选择默认项。

至此, SQL SERVER 2005 同步复制就完成了。使用复制技术,用户可以将一份客户端的数据发布到多台服务器上,从而使不同的服务器用户都可以在权限的许可的范围内共享这份数据。复制技术可以确保分布在不同地点的数据自动同步更新,从而保证数据的一致性,就无需编程实现客户端和服务器端数据同步了!大大提高了工作效率!

SQL Server 2000订阅与发布的具体操作
同步过程
  一、准备工作,如果完成则可跳过。
  1、内网DB服务器作为发布服务器,外网DB服务器作为订阅服务器。
  发布服务器和订阅服务器上分别创建Windows用户jl,密码jl,隶属于administrators,注意要保持一致。
  2、发布服务器上创建一个共享目录,作为发布快照文件的存放目录。例如:在D盘根目录下建文件夹名为SqlCopy,设置用户jl,权限为完全控制。
  3、确定发布服务器和订阅服务器的数据库autoweb保持一致。
  4、在发布服务器和订阅服务器的SQL Server中创建用户登陆名jl,作为发布数据库autoweb的拥有者(设置为dbo_owner和public)。用户名和密码都一致。
  5、打开服务(控制面板---管理工具---服务)
  ---右击SQLSERVER AGENT---属性---登录---选择“此帐户”
  ---输入或选择第一步中创建的WINDOWS 用户jl,
  ---“密码“中输入该用户密码jl
  6、开启SQL Server 2000的网络协议TCP/IP和管道命名协议并重启网络服务。
  7、设置SQL SERVER 身份验证,解决连接时的权限问题(发布、订阅服务器均设置)
  步骤为:对象资源管理器----右击SQL实例-----属性----安全性----服务器身份验证------选“SQL Server和WINDOWS“,然后点确定。
  8、发布服务器和订阅服务器互相注册
  步骤如下:视图----单击以注册服务器----右键数据库引擎----新建服务器注册-----填写要注册的远程服务器名称------身份验证选“SQL Server验证“-----用户名(sa) 密码------创建组(也可不建)-----完成。对于只能用IP,不能用计算机名的,为其注册服务器别名
  二、发布和订阅
  如下工作都在发布服务器上配置,包括发布和订阅。
  快照发布和订阅
  1、 选择 复制 节点,右键本地发布 ----下一步---------系统弹出对话框看提示----直到“指定快照文件夹”----在“快照文件夹“中输入准备工作中创建的目录(指向步骤3所建的共享文件夹)------选择发布数据库-------选择发布类型
  下一步―――选择要发布的数据库autoweb中的表,将b(B)开头的表去掉,V开头的表去掉,c_开头的表去掉,t_开头的表去掉,剩下的表作为快照发布到订阅服务器上(单向传输)
  根据情况决定执行发布的间隔时间,如图每天每20分钟执行一次。
  下一步快照代理安全性,设置如图,连接到发布服务器用户jl,密码jl.
  -------填写发布名称。
  2、 选择 复制 节点,右键本地订阅,选择发布服务器-------选择订阅方式(选择推送订阅))-------填加订阅服务器--------选择代理计划(一般选择连续运行)---------其余选择默认项。
  至此完成快照发布和订阅。
  合并发布和订阅
  1、选择如下三个表作为合并发布的对象,用于双向通讯
  根据情况决定执行发布的间隔时间,如图每天每20分钟执行一次。
  2、 选择 复制 节点,右键本地订阅,选择发布服务器-------选择订阅方式(选择推送订阅))-------填加订阅服务器--------选择代理计划(一般选择连续运行)---------其余选择默认项。
  至此完成合并发布和订阅
  -------------------------------------------------------------------
  主要是要注意权限的问题,一般做发布/订阅,建议你做如下准备工作:
  1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户
  我的电脑
  --控制面板
  --管理工具
  --计算机管理
  --用户和组
  --右键用户
  --新建用户
  --建立一个隶属于administrator组的登陆windows的用户
  2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作:
  我的电脑--D: 新建一个目录,名为: PUB
  --右键这个新建的目录
  --属性--共享
  --选择"共享该文件夹"
  --通过"权限"按纽来设置具体的用户权限,保证第一步中创建的用户具有对该文件夹的所有权限
  --确定
  3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置)
  开始--程序--管理工具--服务
  --右键SQLSERVERAGENT
  --属性--登陆--选择"此账户"
  --输入或者选择第一步中创建的windows登录用户名
  --"密码"中输入该用户的密码
  4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置)
  企业管理器
  --右键SQL实例--属性
  --安全性--身份验证
  --选择"SQL Server 和 Windows"
  --确定
  5.在发布服务器和订阅服务器上互相注册
  企业管理器
  --右键SQL Server组
  --新建SQL Server注册...
  --下一步--可用的服务器中,输入你要注册的远程服务器名--添加
  --下一步--连接使用,选择第二个"SQL Server身份验证"
  --下一步--输入用户名和密码
  --下一步--选择SQL Server组,也可以创建一个新组
  --下一步--完成
  6.对于只能用IP,不能用计算机名的,为其注册服务器别名
  (在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP)
  开始--程序--Microsoft SQL Server--客户端网络实用工具
  --别名--添加
  --网络库选择"tcp/ip"--服务器别名输入SQL服务器名
  --连接参数--服务器名称中输入SQL服务器ip地址
  --如果你修改了SQL的端口,取消选择"动态决定端口",并输入对应的端口号

数据库方向上的9种职业

有大半年没有来MSSQL板块了,看到一些很熟悉的ID都升星了,在此一并恭喜啦!!呵呵
写了一篇心得和大家共勉,并散分。
--------------------------------------------------------------

这几天泡在“三十而立”那个板块,看到很多朋友(从20岁以下到35岁以上,呵呵)都有很多感触或者迷惑。
所谓“人无远虑,必有近忧”,如果等到了30岁还不知道自己想干什么,能干什么,那也许是一种遗憾或者悲哀。

在MSSQL这个板块也偶尔看到一些朋友问关于发展方向和重点等方面的问题。
我不敢说自己的数据库专业知识有多强,毕竟这个世界很大,牛人极多。
只是想把自己在数据库这个方向上亲身做过的,遇到和看得到一些职位大致总结一下,
这些职位都是实实在在的贴在招聘各种网站上的,我也有机会和一些职位上的朋友或同事工作过。

希望对大家确定自己的职业方向和重点有一点帮助。

如果总结得不准确或者有误,请各位高手指正。只有通过讨论和交流才能共同提高。
如果不介意的话,也欢迎大家回帖时不妨透露下自己的方向,或者目标吧。:)

自己先带个头:98年本科毕业,使用过dBase, Foxpro, Informix, Sybase, DB2, MySQL, MSSQL, Oracle,
对Windows和Unix(hp-ux, aix, solaris, linux)都还可以(但比专门的系统管理员还差不少,呵呵),
前面3,5年主要在Unix和Windows上主要从事数据库应用开发,后来又读了2年书,
后面这几年逐渐转到DBA这个方向上,现在做的最多的是SQL Server,也涉及DB2和Oracle。

-----------------------------------------------------------------------
数据库方向上的九种职业。(除了那些数据库研发等太过专业的方向)
前面四种的重点是设计和应用,侧重于软件和数据逻辑层面。
后面五种的重点是运营和维护,侧重与硬件和数据物理层面。
不过这些职位不是孤立,反而是互相交叉的,只是侧重点不同。

说实在的,这些职位没有好与不好之分,每个方向都可以做得很好,
全凭个人的兴趣和目标,但是因为有些职位需求相对少,有机会接触的人不多,
结果就物以稀罕为贵,市场需求决定价值,呵呵。


前面四种:
数据库应用开发 (application development)
除了基本的SQL方面的知识,还要对开发流程,软件工程,各种框架和开发工具等等
数据库应用开发这个方向上的机会最多,职位最多,薪水一般
数据建模专家 (data modeler)
除了基本的SQL方面的知识,非常熟悉数据库原理,数据建模
负责将用户对数据的需求转化为数据库物理设计和物理设计
这个方向上在大公司(金融,保险,研究,软件开发商等)有专门职位,
在中小公司则可能由程序员承担。
商业智能专家 (business intelligence - BI)
主要从商业应用,最终用户的角度去从数据中获得有用的信息,
涉及OLAP (online analytical processing)
需要使用SSRS, cognos, crystal report等报表工具,或者其他一些数据挖掘,统计方面的软件工具
这个方面我不熟悉,不敢乱说(以免被拍砖,呵呵)
数据构架师 (Data Architect)
主要从全局上制定和控制关于数据库在逻辑这一层的大方向,
也包括数据可用性,扩展性等长期性战略,
协调数据库的应用开发,建模,DBA之间的工作。
这个方向上在大公司(金融,保险,研究,软件开发商等)有专门职位,
在中小公司或者没有这个职位,或者由开发人员,DBA负责。

前面五种:
数据库管理员 (database administrator - DBA)
数据库的安装,配置,调优,备份/恢复,监控,自动化等,
协助应用开发(有些职位还要求优化SQL,写存储过程和函数等)
这个方向上的职位相对少一些,但一般有点规模的公司还是会有这样的职位
数据仓库专家 (data warehouse - DW)
应付超大规模的数据,历史数据的存储,管理和使用,
和商业智能关系密切,很多时候BI和DW是放在一个大类里面的,
但是我觉得DW更侧重于硬件和物理层上的管理和优化。
存储工程师 (storage engineer)
专门负责提供数据存储方案,使用各种存储技术满足数据访问和存储需求,
和DBA的工作关系比较密切。
对高可用性有严格要求(比如通信,金融,数据中心等)的公司通常有这种职位,
这种职位也非常少。
性能优化工程师 (performance engineer)
专长数据库的性能调试和优化,为用户提供解决性能瓶颈方面的问题。
我知道至少IBM, 微软和Oracle都有专门的数据库性能实验室(database performance lab),
也有专门的性能优化工程师,负责为其数据库产品和关键应用提供这方面的技术支持。
对数据库性能有严格要求的公司(比如金融行业)可能会有这种职位。
因为针对性很强,甚至要求对多种数据库非常熟悉,所以职位极少。
高级数据库管理员 (senior DBA)
在DBA的基础上,还涉及上面3种职位的部分工作,具体包括下面这些:
对应用系统的数据(布局,访问模式,增长模式,存储要求等)比较熟悉。
对性能优化非常熟悉,可以发现并优化从SQL到硬件I/O,网络等各个层面上的瓶颈
对于存储技术相对熟悉,可能代替存储工程师的一些工作,
对数据库的高可用性技术非常熟悉(比如MSSQL的集群,ORACLE RAC/FailSafe, IBM的DPF, HADR等)
对大规模数据库有效进行物理扩展(比如表分区)或者逻辑扩展(比如数据库分区,联合数据库等)
熟悉各种数据复制技术,比如单向,双向,点对点复制技术,以满足应用要求。
灾难数据恢复过程的建立,测试和执行
这种职位一般只在对数据库要求非常高并且规模非常大(比如金融,电信,数据中心等)的公司需要,
而且这种公司一般有一个专门独立负责数据库的部门或组。
这种职位非常少。


感触:
1) DBA的路不算太好走,我花了10年时间从开发做到DBA,走了些弯路,深刻理解“目标”的重要性
2) SQL Server可以随便装一个玩玩,但也可以玩的很大很复杂,呵呵(这一点我很佩服微软)
3) SQL Server的大规模部署是有的,在性能要求苛刻的OLTP应用上可以和ORACLE,DB2有得一比,
不过,Oracle在高可用性和扩展性上的确有一些优势,而且市场做得极好,但配置和管理也相对复杂。
但在超大数据仓库方面,DB2和Teradata很强,Oracle和MSSQL还需要再努力,不过这是基本构架上的问题。

5种提高SQL性能的方法

有时, 为了让应用程序运行得更快,所做的全部工作就是在这里或那里做一些很小调整。啊,但关键在于确定如何进行调整!迟早您会遇到这种情况:应用程序中的 SQL 查询不能按照您想要的方式进行响应。它要么不返回数据,要么耗费的时间长得出奇。如果它降低了报告或您的企业应用程序的速度,用户必须等待的时间过长,他们就会很不满意。就像您的父母不想听您解释为什么在深更半夜才回来一样,用户也不会听你解释为什么查询耗费这么长时间。(“对不起,妈妈,我使用了太多的 LEFT JOIN。”)用户希望应用程序响应迅速,他们的报告能够在瞬间之内返回分析数据。就我自己而言,如果在 Web 上冲浪时某个页面要耗费十多秒才能加载(好吧,五秒更实际一些),我也会很不耐烦。

为了解决这些问题,重要的是找到问题的根源。那么,从哪里开始呢?根本原因通常在于数据库设计和访问它的查询。在本月的专栏中,我将讲述四项技术,这些技术可用于提高基于 SQL Server? 的应用程序的性能或改善其可伸缩性。我将仔细说明 LEFT JOIN、CROSS JOIN 的使用以及 IDENTITY 值的检索。请记住,根本没有神奇的解决方案。调整您的数据库及其查询需要占用时间、进行分析,还需要大量的测试。这些技术都已被证明行之有效,但对您的应用程序而言,可能其中一些技术比另一些技术更适用。

从 INSERT 返回 IDENTITY 我决定从遇到许多问题的内容入手:如何在执行 SQL INSERT 后检索 IDENTITY 值。通常,问题不在于如何编写检索值的查询,而在于在哪里以及何时进行检索。在 SQL Server 中,下面的语句可用于检索由最新在活动数据库连接上运行的 SQL 语句所创建的 IDENTITY 值:

SELECT @@IDENTITY这个 SQL 语句并不复杂,但需要记住的一点是:如果这个最新的 SQL 语句不是 INSERT,或者您针对非 INSERT SQL 的其他连接运行了此 SQL,则不会获得期望的值。您必须运行下列代码才能检索紧跟在 INSERT SQL 之后且位于同一连接上的 IDENTITY,如下所示:

INSERT INTO Products (ProductName) VALUES ('Chalk') SELECT @@IDENTITY在一个连接上针对Northwind 数据库运行这些查询将返回一个名称为 Chalk 的新产品的 IDENTITY 值。所以,在使用 ADO 的 Visual Basic? 应用程序中,可以运行以下语句:

Set oRs = oCn.Execute("SET NOCOUNT ON;INSERT INTO Products _
(ProductName) VALUES ('Chalk');SELECT @@IDENTITY")
lProductID = oRs(0)此代码告诉 SQL Server 不要返回查询的行计数,然后执行 INSERT 语句,并返回刚刚为这个新行创建的 IDENTITY 值。SET NOCOUNT ON 语句表示返回的记录集有一行和一列,其中包含了这个新的 IDENTITY 值。如果没有此语句,则会首先返回一个空的记录集(因为 INSERT 语句不返回任何数据),然后会返回第二个记录集,第二个记录集中包含 IDENTITY 值。这可能有些令人困惑,尤其是因为您从来就没有希望过 INSERT 会返回记录集。之所以会发生此情况,是因为 SQL Server 看到了这个行计数(即一行受到影响)并将其解释为表示一个记录集。因此,真正的数据被推回到了第二个记录集。当然您可以使用 ADO 中的 NextRecordset 方法获取此第二个记录集,但如果总能够首先返回该记录集且只返回该记录集,则会更方便,也更有效率。

此方法虽然有效,但需要在 SQL 语句中额外添加一些代码。获得相同结果的另一方法是在 INSERT 之前使用 SET NOCOUNT ON 语句,并将 SELECT @@IDENTITY 语句放在表中的 FOR INSERT 触发器中,如下面的代码片段所示。这样,任何进入该表的 INSERT 语句都将自动返回 IDENTITY 值。

CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS
SELECT @@IDENTITY
GO
触发器只在 Products 表上发生 INSERT 时启动,所以它总是会在成功 INSERT 之后返回一个 IDENTITY。使用此技术,您可以始终以相同的方式在应用程序中检索 IDENTITY 值。

内嵌视图与临时表
某些时候,查询需要将数据与其他一些可能只能通过执行 GROUP BY 然后执行标准查询才能收集的数据进行联接。例如,如果要查询最新五个定单的有关信息,您首先需要知道是哪些定单。这可以使用返回定单 ID 的 SQL 查询来检索。此数据就会存储在临时表(这是一个常用技术)中,然后与 Products 表进行联接,以返回这些定单售出的产品数量:

CREATE TABLE #Temp1 (OrderID INT NOT NULL, _
OrderDate DATETIME NOT NULL)
INSERT INTO #Temp1 (OrderID, OrderDate)
SELECT TOP 5 o.OrderID, o.OrderDate
FROM Orders o ORDER BY o.OrderDate DESC
SELECT p.ProductName, SUM(od.Quantity) AS ProductQuantity
FROM #Temp1 t
INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
GROUP BY p.ProductName
ORDER BY p.ProductName
DROP TABLE #Temp1这些 SQL 语句会创建一个临时表,将数据插入该表中,将其他数据与该表进行联接,然后除去该临时表。这会导致此查询进行大量 I/O 操作,因此,可以重新编写查询,使用内嵌视图取代临时表。内嵌视图只是一个可以联接到 FROM 子句中的查询。所以,您不用在 tempdb 中的临时表上耗费大量 I/O 和磁盘访问,而可以使用内嵌视图得到同样的结果:

SELECT p.ProductName,
SUM(od.Quantity) AS ProductQuantity
FROM (
SELECT TOP 5 o.OrderID, o.OrderDate
FROM Orders o
ORDER BY o.OrderDate DESC
) t
INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
GROUP BY
p.ProductName
ORDER BY
p.ProductName此查询不仅比前面的查询效率更高,而且长度更短。临时表会消耗大量资源。如果只需要将数据联接到其他查询,则可以试试使用内嵌视图,以节省资源。



避免 LEFT JOIN 和 NULL


当然,有很多时候您需要执行 LEFT JOIN 和使用 NULL 值。但是,它们并不适用于所有情况。改变 SQL 查询的构建方式可能会产生将一个花几分钟运行的报告缩短到只花几秒钟这样的天壤之别的效果。有时,必须在查询中调整数据的形态,使之适应应用程序所要求的显示方式。虽然 TABLE 数据类型会减少大量占用资源的情况,但在查询中还有许多区域可以进行优化。SQL 的一个有价值的常用功能是 LEFT JOIN。它可以用于检索第一个表中的所有行、第二个表中所有匹配的行、以及第二个表中与第一个表不匹配的所有行。例如,如果希望返回每个客户及其定单,使用 LEFT JOIN 则可以显示有定单和没有定单的客户。

此工具可能会被过度使用。LEFT JOIN 消耗的资源非常之多,因为它们包含与 NULL(不存在)数据匹配的数据。在某些情况下,这是不可避免的,但是代价可能非常高。LEFT JOIN 比 INNER JOIN 消耗资源更多,所以如果您可以重新编写查询以使得该查询不使用任何 LEFT JOIN,则会得到非常可观的回报。

加快使用 LEFT JOIN 的查询速度的一项技术涉及创建一个 TABLE 数据类型,插入第一个表(LEFT JOIN 左侧的表)中的所有行,然后使用第二个表中的值更新 TABLE 数据类型。此技术是一个两步的过程,但与标准的 LEFT JOIN 相比,可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间,直到获得用于您的应用程序的执行性能最佳的查询。

测试查询的速度时,有必要多次运行此查询,然后取一个平均值。因为查询(或存储过程)可能会存储在 SQL Server 内存中的过程缓存中,因此第一次尝试耗费的时间好像稍长一些,而所有后续尝试耗费的时间都较短。另外,运行您的查询时,可能正在针对相同的表运行其他查询。当其他查询锁定和解锁这些表时,可能会导致您的查询要排队等待。例如,如果您进行查询时某人正在更新此表中的数据,则在更新提交时您的查询可能需要耗费更长时间来执行。

避免使用 LEFT JOIN 时速度降低的最简单方法是尽可能多地围绕它们设计数据库。例如,假设某一产品可能具有类别也可能没有类别。如果 Products 表存储了其类别的 ID,而没有用于某个特定产品的类别,则您可以在字段中存储 NULL 值。然后您必须执行 LEFT JOIN 来获取所有产品及其类别。您可以创建一个值为“No Category”的类别,从而指定外键关系不允许 NULL 值。通过执行上述操作,现在您就可以使用 INNER JOIN 检索所有产品及其类别了。虽然这看起来好像是一个带有多余数据的变通方法,但可能是一个很有价值的技术,因为它可以消除 SQL 批处理语句中消耗资源较多的 LEFT JOIN。在数据库中全部使用此概念可以为您节省大量的处理时间。请记住,对于您的用户而言,即使几秒钟的时间也非常重要,因为当您有许多用户正在访问同一个联机数据库应用程序时,这几秒钟实际上的意义会非常重大。灵活使用笛卡尔乘积。对于此技巧,我将进行非常详细的介绍,并提倡在某些情况下使用笛卡尔乘积。出于某些原因,笛卡尔乘积 (CROSS JOIN) 遭到了很多谴责,开发人员通常会被警告根本就不要使用它们。在许多情况下,它们消耗的资源太多,从而无法高效使用。但是像 SQL 中的任何工具一样,如果正确使用,它们也会很有价值。例如,如果您想运行一个返回每月数据(即使某一特定月份客户没有定单也要返回)的查询,您就可以很方便地使用笛卡尔乘积。 图 2 中的 SQL 就执行了上述操作。

虽然这看起来好像没什么神奇的,但是请考虑一下,如果您从客户到定单(这些定单按月份进行分组并对销售额进行小计)进行了标准的 INNER JOIN,则只会获得客户有定单的月份。因此,对于客户未订购任何产品的月份,您不会获得 0 值。如果您想为每个客户都绘制一个图,以显示每个月和该月销售额,则可能希望此图包括月销售额为 0 的月份,以便直观标识出这些月份。如果使用 图 2 中的 SQL,数据则会跳过销售额为 0 美元的月份,因为在定单表中对于零销售额不会包含任何行(假设您只存储发生的事件)。

图 3 中的代码虽然较长,但是可以达到获取所有销售数据(甚至包括没有销售额的月份)的目标。首先,它会提取去年所有月份的列表,然后将它们放入第一个 TABLE 数据类型表 (@tblMonths) 中。下一步,此代码会获取在该时间段内有销售额的所有客户公司的名称列表,然后将它们放入另一个 TABLE 数据类型表 (@tblCus-tomers) 中。这两个表存储了创建结果集所必需的所有基本数据,但实际销售数量除外。 第一个表中列出了所有月份(12 行),第二个表中列出了这个时间段内有销售额的所有客户(对于我是 81 个)。并非每个客户在过去 12 个月中的每个月都购买了产品,所以,执行 INNER JOIN 或 LEFT JOIN 不会返回每个月的每个客户。这些操作只会返回购买产品的客户和月份。

笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘,生成一个行集合,其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此,笛卡尔乘积会向表 @tblFinal 返回 972 行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新 @tblFinal 表,以及选择最终的行集。

如果由于笛卡尔乘积占用的资源可能会很多,而不需要真正的笛卡尔乘积,则可以谨慎地使用 CROSS JOIN。例如,如果对产品和类别执行了 CROSS JOIN,然后使用 WHERE 子句、DISTINCT 或 GROUP BY 来筛选出大多数行,那么使用 INNER JOIN 会获得同样的结果,而且效率高得多。如果需要为所有的可能性都返回数据(例如在您希望使用每月销售日期填充一个图表时),则笛卡尔乘积可能会非常有帮助。但是,您不应该将它们用于其他用途,因为在大多数方案中 INNER JOIN 的效率要高得多。

拾遗补零
这里介绍其他一些可帮助提高 SQL 查询效率的常用技术。假设您将按区域对所有销售人员进行分组并将他们的销售额进行小计,但是您只想要那些数据库中标记为处于活动状态的销售人员。您可以按区域对销售人员分组,并使用 HAVING 子句消除那些未处于活动状态的销售人员,也可以在 WHERE 子句中执行此操作。在 WHERE 子句中执行此操作会减少需要分组的行数,所以比在 HAVING 子句中执行此操作效率更高。HAVING 子句中基于行的条件的筛选会强制查询对那些在 WHERE 子句中会被去除的数据进行分组。

另一个提高效率的技巧是使用 DISTINCT 关键字查找数据行的单独报表,来代替使用 GROUP BY 子句。在这种情况下,使用 DISTINCT 关键字的 SQL 效率更高。请在需要计算聚合函数(SUM、COUNT、MAX 等)的情况下再使用 GROUP BY。另外,如果您的查询总是自己返回一个唯一的行,则不要使用 DISTINCT 关键字。在这种情况下,DISTINCT 关键字只会增加系统开销。

您已经看到了,有大量技术都可用于优化查询和实现特定的业务规则,技巧就是进行一些尝试,然后比较它们的性能。最重要的是要测试、测试、再测试。在此专栏的将来各期内容中,我将继续深入讲述 SQL Server 概念,包括数据库设计、好的索引实践以及 SQL Server 安全范例。

asp.net中判断链接是否来自外部

以前在asp中我们使用如下方法进行判断

<%
Server_url1=Cstr(Request.ServerVariables("HTTP_REFERER"))
Server_url2=Cstr(Request.ServerVariables("Server_Name"))
if Server_url1<>"" then
If Mid(Server_url1,8,len(Server_url2)) <>Server_url2Then
Response.End
End If
end if
%>

在asp.net中我们使用的方法是
public bool IsUrl()
{
string str1 = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_REFERER"];
string str2 = System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
return ((str1 != null) && (str1.IndexOf(str2) == 7));
}

Java与.NET,谁是未来?

为什么会有Java,为什么会有.NET

有人说,Java是为了跨Windows和UNIX而产生的。是这样吗?

  Sun有自己的操作系统solaris,并且打的是高端市场,而Java发展早期阶段,Windows还主要定位在中小型企业,并没有打算与Sun一争高端客户。

  而且Sun的用户大部分都是大型企业级,而Windows定位在家庭消费用户,由于Windows已经成为桌面OS的事实标准,Sun根本无意抢夺 Windows的地盘,而且Sun有自己的操作系统,扩大自己产品销售才是第一。

  但是UNIX一直是个混乱的世界,各种UNIX版本在并存,你为这种 UNIX开发的应用,却很难在另一种UNIX上跑通.应用的阻塞影响了UNIX市场需求的扩大,就象没有SQL Server,没有OFFICE,没有Windows 游戏,和Windows上的开发工具,就算你的操作系统做的再漂亮再容易我们也会扔掉Windows.为什么?因为没用,我买回来一个大铁家伙,我什么也做不了.Sun就出于这种考虑,所以才有VM的想法,否则谁傻了,做个又慢又麻烦的VM.所以说Java的产生,只是为了跨UNIX平台.当然能跨 Windows,吃定Windows,那岂不是更好,呵呵呵,Sun为自己的妙招而没事偷着乐.

  那为什么会有.NET呢?可是Windows就一个呀,它也要跨平台?而且微软已经把CLI提交给标准委员会,看来是真要跨了?真的吗?

  从外表来看,Windows确实是一个.但是从技术角度来看,Windows3,Windows95,Windows2000是截然不同的三种架构.在中国,大家对新技术的追求比较热衷,所以说一个企业中这三种操作系统并存互连的可能性不怎么大.但是老外是精打细算,不见兔子不撒鹰,所以你在国外企业运行很老的系统也不要见怪.微软为了同时维护这几种操作系统也是煞费苦心,而且由于技术是各个时期形成的,有的技术由于历史发展原因有明显的缺陷,也无能为力修改了,而且为了功能更强大,API海洋,DLL黑洞,ACTIVEX,OLE,COM,DCOM,COM+,各种技术交叉,唉,其中苦谁了解?所以跨WINDWOS平台是微软制造.NET的一个原因,这样给你一个抽象的统一的平台后把你摆平后,他再着手修改他的底层,省得一天人们叫着 Windows不安全,Windows不稳定.当然从J2EE的火热场面来看,拉去了很大一批Windows平台上的C++程序员.失去了应用开发的源头,那还有什么发展?如何拉回这批程序员让他们继续为Windows开发当然也是.NET的原因之一,这就是为什么.NET从架构到开发语言都与 Java极其相似的原因,就是吸引你平滑的再回到微软的世界中,如果跨度大了,程序员就有了迟疑.唉,如果没有Java,如今的C#也不会是如今这样,原本它会更好,我想ANDERS一定心中很郁闷,但是商业是不以个人意志为转移的.而且现在已经不是桌面为王的时代了,现在是互连网的时代,Java是第一个有强大开发WEB应用的完整体系,而当时微软的技术还是七拼八凑,只是互连网一下到来微软刚醒过神来仓促应战的结果,当然无法与J2EE媲美.想在互连网时代也分一杯羹,必须也有一个完整的体系,于是.NET就产生了.

我们已经有了Web Service,我们还需要.NET吗?

  其实技术发展到如今的应用集成时代,用户的需求就是把现在各种平台上的应用集成起来.集成的方法有很多种,当然跨平台也是一种.不过最省力的还算是WEB SERVICE.因为现在已经是组件应用的天下.各种COM,EJB,CORBA成为快速组装企业应用的主流技术.组件是位于操作系统,数据库,网络之上的技术,站在组件的层面上,下面用什么技术已经无所谓了,因为已经被组件屏蔽了.如果我们能把我们的组件互连起来,不也可以集成吗?应该怎么做?这几项技术都分属于不同公司,想联合真不大容易.这时就要找到每个体系公共的东西,用公共的东西把他们连在一起不就行了.找呀找,终于发现,是TCP/IP.随即几大公司都发现了突破口,需要快速占领先机.由于Sun一直在Java发展的问题上给了IBM很大的阻塞,所以IBM宁愿先和微软联合做,如果微软有什么不轨之心,就放出Sun,让他们互相咬,然后在适当的时机出来装出老大的样子摆平他们,给他们俩制定一个适合自己发展的竞争协议.

  我们已经可以互连了,我们干吗要.NET.我们的问题已经解决了,我干吗花钱再投资呢?经济本来已经很不景气了.

  但是,但是,就是这该死的但是...

  微软看来已经决定不在现有基础上增强ASP和COM+了,现在是互连时代,也是组件时代,两大要命的地方我都不升级了,你自己看着办,我可没逼着你买.

.NET和Java在中国哪个更有前途?

  这个问题好象已经不用再争了.中国90%的用户是Windows用户,保护现有投资,使用很习惯很易用不用重新学习,我又不用跨平台,我干吗要换Java 呢.过去是微软没有提供很强大的WEB开发解决方案,现在提供了,我干吗要用Java.而且. Net比Java出的迟,肯定会吸收Java的优点,弥补Java的缺点.而且微软的VM肯定和Windows结合的很好,性能不用担心.我干吗用 Java?而且微软显然把宝已经压到了.NET上,你难道还要在.NET的VM上再加一层Java的VM?

.NET有什么新的亮点?

  当然是ASP,ADO和COM+,还有清晰的架构,并且由于统一的类库,我们为WEB,GUI,MOBILE而开发的应用会很容易的转来转去,不象过去开发,各需要学习不同的知识.ASP终于结束了网页意大利面条式的程序,面向对象和支持多种语言,使构筑强大复杂的WEB应用提供了比JSP更凶猛的功能,让人不得不爱.ADO.NET也抛弃了过去的数据集一Scroll就连数据库进行提交的糟糕速度,代而取之的是多条修改可以一次性提交上去.这样性能会提高很多.COM+呢?COM+1.5的特性大家在WINXP上也看见了,比1.0强了很多,未来还不用注册, COPY完就能用,多舒服.至于安全嘛,稳定嘛,这话不敢讲.因为盗亦有道,Java也同样如此,无法说谁比谁好.

.NET真的会跨平台吗?

  微软的命根子是操作系统,微软此次出.NET也是为了打入高端市场.怎么打入?微软第一已经在用C#收买 Java程序员了,并且做Java和C#的映射工具,先断了Java应用的前途,后面用CLI提交给标准委员会,让别人开发UNIX上的平台,微软不在正面和UNIX阵营冲突,以免犯众怒.当UNIX和Windows的CLI都有了时候,基于CLI的应用可就两个系统都能用了,这会帮助微软销售多少其他产品呀.这不,微软在支持着好几个Open Source社团在开发UNIX的CLI.跨平台的事微软不会轻易干的,否则微软的命根子怎么办?

.NET真的支持多种语言吗?

  开发更多的基于.NET的应用,让.NET快速成长起来.第二.NET是一次比较大的革新,广大的各类程序员能否跟的上也是个问题.多语言的支持当然会,但是不会支持的很好,否则微软大力做C#干吗呀,如果别的语言和C#一样好,那微软还混什么混呀.最糟糕了,也要其他语言的技术比C#慢半拍.不过先走也未必领先,就象DELPHI就后来居上,这么大的市场,微软是不可能通吃的.

我们需要转到.NET上吗?

  你可以不转.就看你需要不需要INTERNET了.我想在未来,没有企业会说INTERNET对我没有一点作用.

现有应用能否平滑过渡呢?

  在这个问题上可以看一下微软的历史.微软在做完WINNT4的时候其实已经在策划现在的WIN2000,但是为什么在WIN95后有WIN98, WINME,WINXP,不是他当时做不了那样的技术,而是必须引导着客户一步步走,要追随客户,走的太快,就会丢失客户.在这个重大的转折点,微软也会如此.而且在现在的Windows.NET上,你运行现在的程序一样没问题,速度依旧,操作方式也依旧,因为他使用了两种手段来区别对待这两种应用程序.

什么时候转?

  如果你需要抢占市场先机,现在转正好,因为能支持ASP.NET,ADO.NET开发的VSS.NET已经推出快一年了,就是有能力欠缺的问题,第二版的出来也不会太晚了.不过话在前头,确实在实际的开发中,Vss.NET确实有些做不了的事情,不要看他好象什么都有,这就跟微软当年宣布COM有池化的功能一样,仅有一个外壳.这是微软的策略,跟不跟着走,你自己看.稳健型的公司建议在第二版出来后应用,因为微软的产品一向在第三版才会好用.

作为开发商,跟随.NET的难点是什么?

  难点难就在,过去我们的开发方式,拖一些控件,连个数据库,更新或SELECT一些数据.再深一些就是消息,或者是一些不常用的API.记住:.NET是微软进攻高端市场的第一步,现在的微软不是我们过去熟悉的微软,Vss.NET的一推出,就是强烈给人一种这样的感受:从建模到开发到测试到发布,全套企业级的工具都无缝相接,而且处处体现着OO和设计模式,在宣传中也频繁提到,昭示着这个工具是为大型应用开发而定制的.所以宝刀也需有能力的人才能拿的动,否则只能砸了自己的脚.对于现在的Java开发工具也是如此,好象全世界一下都没有了小型企业一样.我们是否具备了优秀的设计师,建模师,OOP的程序员,我们是否有一整套流畅的开发流程来支持全程建模,我们都需要深思.在微软的.NET的各种培训上,培训师也是反复强调分析设计,大型项目管理,自动化工具的支持,你做好准备了吗?

题外话:

Sun在微软拆分问题上输了吗?

  微软的案子打了这么多年,居然庭外和解.Sun确实挺郁闷.不过Sun并没有输.为什么这么说呢?依毛主席的话说就是:敌进我退,敌疲我扰.确实微软在. NET的发展上受了很多牵绊,否则也不会到如今才推出来个框架.在硅谷,时间就是机会,时间就是金钱,谁前进的快谁就能占先机,显然Sun并不是最痛苦的一个.

Java的未来

  依Windows的用户量和微软进攻高端企业应用的决只是呆板的图形,不能全方位的表现网络的传输技术,使应用进步更加依赖硬件而不是软件,微软亚洲研究院为什么在做哪些研究,就是因为他们不断在思考未来是什么,所以每一次技术的浪潮他们总在浪头.当然未来还会有所改变,但是他们会及时调整他们的战略,但大方向不会错到哪去!

  当技术不再是阻碍应用发展的主要因素,比如宽带的来临,这时候你想过没有,在它上面,该做些什么呢?

  世界有多大,你能看多远?为什么在每次浪潮到来时你都无法预想到,而感叹这世界变化如此之快?

我对微软的发展的一些看法:

  微软把.NET扩展到高端市场和移动设备市场,为.NET开发的程序可以在基于.NET的任何设备上都可以运行,大家不需要为不同的设备用不同的工具开发应用,应用极大的推动了基础软件的扩大,就象OFFICE,SQL Server辅助扩大了Windows的销售一样.

  未来的XBOX也会变成.NET平台,成为家庭连网的安全网关和交易网关和信息网关,如果你觉得微软进入游戏业就是为了眼馋游戏这块利润,那你就大错特错了,这个皮毛根本不值得微软大动这么财力.

  PDA 和手机也和机顶盒一样嵌入.NET,你打开电视,你打电话,你玩游戏,你工作,你上网,你甚至打开冰箱,你都不会知道在背后支撑的是.NET,从高端服务器到你的手机,全部是微软的软件这是一个伟大的设想,如果微软能够兢兢业业的走,凭这样的财力人力和管理和经营战略,走10年,实现的可能性非常大,这不是以个人意志为转移的,你说他倒他就会倒吗?

  如果会成功,当然微软会成为人类历史上最伟大的公司,赚取的财富已经不能再提,最关键的问题是:我们全人类的生活和工作被一个私人的商业公司所控制着.

  只是到那个恐怖的地步,你是否有勇气和能力把他拆分.因为他足以触及到你的生活和工作,社会的经济,政治活动,甚至军事,任何的动作都足以引起社会的大地震.

  你认为他有什么理由完不成这些梦想吗?

维基百科推出富文本编辑功能 今年聚焦易用性

最近,维基百科一名高层在接受采访时表示,今年维基百科的主要目标是提高网站易用性,其中网站最近已经推出了富文本编辑功能.

作出上述表态的人是Wikia公司的联合创始人安哥拉·比斯丽.Wikia是维基百科创始人吉米·威尔斯创建的营利性公司.这位高层在接受采访时表示,Wikia和维基百科今年的焦点是提高易用性.最近,维基传媒基金会获得了89万美元的捐款,将用于改进网站界面.

最近,Wikia推出了一个“所见即所得”的富文本编辑器,已经部署到了维基百科中.用户在修改词条时,无须再学习标记术语,直接用工具处理粗体、斜体、表格等.

与此同时,老用户仍然可以使用传统的标记风格的词条编辑模式.

另外,维基百科最近还推出了一种新的站点风格,可以让读者更方便地浏览词条文章,并且进行编辑.

JPEG新标准将在2009年制定 图像质量可提高两倍

JPEG XR是微软创立的图像格式,微软承诺前者比JPEG有诸多优点。目前,JPEG XR已经清除了标准化的核心障碍。

联合图像专家组(Joint Photographic Experts Group,最初创立JPEG格式标准的组织),在1月的一次会议表决中表示,“我们希望JPEG XR国际标准将在今年晚些时候发布。”XR是“扩展范围(extended range)”的缩写,意味着其提供了更好的动态范围——跨度在图像中最明亮处和最黑暗处之间。

JPEG使用8位元编码,实现了256色。JPEG则能使用16位元或更多,提供了更好的效果和更多的编辑灵活性。

JPEG XR的另一个优点是,其使用更加高效率的压缩算法,与JPEG文件同等大小的情况下,图像质量是后者的两倍,或同等质量只需一半的体积。并且与JPEG不同,JPEG XR的最高质量压缩不丢失任何信息。

JPEG XR可以将图像分成每小部分来解码,使图像的放大更加迅速。微软不仅通过软件使用该格式,还将该技术嵌入到相机图像处理器电路中。

微软希望JPEG XR能够广泛采用,但是替代仍然大行其道的JPEG格式面临很大挑战。

70%中国软件企业竞争力不足 国产软件份额较低

随着全球金融危机影响进一步扩大, 2009年的软件行业也同样面临严峻挑战。 但有关专家指出,在经济不景气和“消费降级”的情况下,我国软件行业机遇与挑战是并存的,如果软件企业能抓住机遇,打好三大战役,熬过“冬天”,就将迎来产业的“柳暗花明”。
整个行业面临严峻挑战
目前软件业整体表现虽然良好,但软件外包短期的不确定性增加。2008年1到11月国内软件业收入同比增长30.8%,增速较上年同期提高了10.8个百分点。但软件外包增速不断放缓。根据外包咨询公司TPI的数据显示,2008年第三季度签署的外包协议金额为6年来季度最低水平,当季金额在2500万美元以上的大额外包协议仅有128项,总价值大约为144亿美元,交易数量较上年同期减少大约 20%,比去年第二季度减少22%,因此,2009年我国软件外包不容乐观。
国内经济下滑也使得软件业面临内需下降的考验。受美国金融危机影响,全球经济衰退,中国也不可能独善其身。削减开支已经成为国内企业“过冬”的重要手段之一。例如,金融、证券等行业的软件需求由于企业利润下滑而降低;商业、制造业等因前景不明,软件需求也有一定程度下降……在这种情况下,国内企业在IT方面的开支必然面临缩水,国内企业IT开支下降会导致软件业增速放缓。
另外制造业的不景气,对管理软件厂商的影响较大,从而也会影响到软件业的发展。CCID的报告显示,2008年第三季度管理软件增速放缓,中小企业倒闭或盈利下降导致IT开支下降是主要原因。从管理软件市场来看,制造业一直是其主要市场。中小制造企业在管理软件市场中占比达60%以上,同时也是近年来管理软件增长最快的市场,而制造业的不景气,导致中小制造企业对管理软件需求的减少,这对管理软件厂商来说不是一件好事。
70%中国软件商竞争力不足
据IDC近期发布的《软件商成长路线图》白皮书显示,中国软件及IT服务产业规模占整个IT产业的比重仅为25.8%,而同期美国的这一比重则高达69.9%。另外,其调查结果还显示,近70%的中国软件开发商竞争力不足。
同时,有关专家也指出,目前国产软件在中国软件市场中所占的份额依然很低,仅约为35%。由于基础技术、核心技术,以及自主知识产权软件产品的缺乏,不仅使得巨额的利润被IBM、微软、BEA、Oracle等一大批国外企业攫走,影响着中国软件产业的积累与再循环能力,而且还严重威胁着国家的战略安全。
关于制约中国软件业发展的瓶颈问题,多年来一直众说纷纭,或曰人才、资金、软件质量,或曰产业生态环境、公共服务体系等等,不过,自主核心技术缺乏无疑是各界人士的共识,也是中国软件产业发展最核心的问题。
中国软件产业起步较晚,产业起步时在很大程度上是“洋为中用”的舶来品,之后在很长一段时间的发展中,也是在模仿和学习西方国家尤其是美国的模式,甚至很多技术和产品直接来自美欧等西方国家。应该说这无可置疑,也是起步阶段的捷径。但随着我国信息化建设的日益深入,软件产业作为战略性产业的价值和地位也越来越明显,其发展水平、发展规模、发展速度都直接关系到国家的经济发展、社会进步和国家安全。
因此,国内专家呼吁,大力扶持和鼓励自主创新,拥有自主核心技术,尤其是软件开发核心技术和应用软件开发平台,才是中国软件产业发展的核心问题和突破瓶颈的关键。
内需市场将加速行业整合
软件企业应看到国内软件市场的巨大前景。虽然“过冬论”在业界盛行,但随着国家大规模扩大内需,软件产品大有用武之地。目前,国内各个行业信息化率仍有提升空间,同时“消费降级”促使企业选择软件支出时,偏向相对低端的国内软件产品。因此,目前国内软件业已经到了最佳投资期,抓住内需市场已经成为软件业未来提升行业景气度的关键所在。
国内软件企业可以在危机中提升整体实力,以便在经济复苏阶段大展拳脚。国家政策非常有利于软件企业的发展。2006年起,原信息产业部及相关部委陆续出台了《加快推进大公司战略》、《国家规划布局内重点软件企业认定管理办法》等有关政策,从税收和研发、经费等方面都加大了对软件企业的支持力度,更加注重扶持优秀企业和鼓励本土企业的自主创新及国际化发展,这为中国软件企业做大做强创造了良好的政策环境。
同时,软件企业可以在经济低迷的时候以较低的代价展开并购、整合,壮大自己。海辉软件集团董事长孙振耀就预测,现在中国有3000家软件服务外包企业,行业整合的序幕已经展开。并购是经济低迷时期到来的一种必然现象,对于持有大量现金的科技公司来说,现在是收购的最佳时机。
金融危机是国内软件企业招揽人才的一个机遇。美国IT行业的裁员风暴,对于目前正在走向世界的中国IT行业来说,是一个难得的招揽IT人才的机遇。据悉,此次席卷全球的金融危机让大批国际IT业巨头纷纷裁员。由于我国IT行业拥有庞大的国内消费市场作为强有力的支撑,而IT人才却较为缺乏。因此,利用这个时机“招兵买马”对于我国软件业来说是一个难得的机会。
逆市上扬还需苦练内功
纵观目前国内软件行业,产品同质化、客户需求多样化等一系列瓶颈导致整个软件产业链停滞不前的局面。业内专家表示,2009年,我国软件业要逆市取得发展必须打赢三大战役。
首先就是要努力做好软件外包。长期来看,服务的外包和离岸是全球经济发展的大势所趋。金融危机的爆发,使得成本缩减成为发包企业的首要任务,将促使其重新界定外包范围,升级与承包商的合作,与其他国家相比,中国软件企业成本优势明显。其次,经济相对高速发展的中国将成为众多跨国公司的“避风港”,中国软件外包企业将会获得更多的发展机遇。
其次是要抓住行业信息化的机遇。政府扩大内需本身会带动城市信息化、农村信息化、工业信息化等方面的发展,这就给软件企业带来了机会。以电力行业为例,国家计划推动1.16万亿元的电网投资,2009年,电网投资规模将达到900亿元。“十一五 ”期间是电力行业信息化的加速发展期,一些大型的IT项目将会逐步落到实处,电力行业信息化向前迈进的步伐将加快。在电力行业向信息化迈进的过程中,与其相关的软件企业必将从中分一杯羹。
最后是要进一步抓住管理软件的商机。在面临经济困境的时候,中小企业需要向管理要效益,管理信息化能为中小企业“抗寒过冬”助一臂之力。使用管理软件,可以帮助中小企业加快资金周转、减少库存压力、降低人力成本,使企业从原来的粗放型管理向精细管理过渡,从而为中小企业寻得生机,因此管理软件这块市场大有潜力可挖,软件企业一定要把握这个商机。商报记者 金朝力
链接跨国公司是中国市场最大赢家
中国科学院院士倪光南日前称,按照工信部的数字,2008年中国软件和信息服务业的产值是5800亿。如果一个软件工程师一年能创造10万元,那么一个公司就能生存下去。倪光南算了一笔账:如果这5800亿都是中国的软件人员创造出来的,那么需要580万的软件人员,而中国目前软件业从业人员仅为120万左右,这说明中国软件业5800亿的产值大部分都落入了跨国公司的囊中。因此倪光南建议,应高度重视软件业的发展。

2009年1月18日星期日

Jdon框架应用系统演示

JdonFramework应用案例之一: JdonFrameworkTest
 展示一个模型的增删改查CRUD以及批量查询功能,两种架构:Struts+Jdon+Jdbc和Struts+Jdon+JPA/Hibernate,下图是整个项目的所有类。  代码量很少,开发效率高,10分钟可以搞定,特别是后者JPA/Hibernate架构,属于纯面向对象系统(pure Object-Oriented),除模型类代码和配置外,其余代码不超过20行,JPA案例中是不用事先建立数据表的,而是在部署时自动创建数据表,将数据库降为软件的运行部署管理阶段,属于系统管理工作。   本案例适合初学者作为学习开发J2EE/JEE/JAVAEE应用系统案例 。
http://www.jdon.com/

初学者如何开发出一个高质量的J2EE系统

  J2EE学习者越来越多,J2EE本身技术不断在发展,涌现出各种概念,本文章试图从一种容易理解的角度对这些概念向初学者进行解释,以便掌握学习J2EE学习方向。
  首先我们需要知道Java和J2EE是两个不同概念,Java不只是指一种语言,已经代表与微软不同的另外一个巨大阵营,所以Java有时是指一种软件系统的流派,当然目前主要是.NET和Java两大主流体系。
  J2EE可以说指Java在数据库信息系统上实现,数据库信息系统从早期的dBase、到Delphi/VB等C/S结构,发展到B/S(Browser浏览器/Server服务器)结构,而J2EE主要是指B/S结构的实现。
  J2EE又是一种框架和标准,框架类似API、库的概念,但是要超出它们。如果需要详细了解框架,可先从设计模式开始学习。
  J2EE是一个虚的大的概念,J2EE标准主要有三种子技术标准:WEB技术、EJB技术和JMS,谈到J2EE应该说最终要落实到这三个子概念上。
  这三种技术的每个技术在应用时都涉及两个部分:容器部分和应用部分,Web容器也是指Jsp/Servlet容器,你如果要开发一个Web应用,无论是编译或运行,都必须要有Jsp/Servlet库或API支持(除了JDK/J2SE以外)。
  Web技术中除了Jsp/Servlet技术外,还需要JavaBeans或Java Class实现一些功能或者包装携带数据,所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。
  谈到JavaBeans技术,就涉及到组件构件技术(component),这是Java的核心基础部分,很多软件设计概念(设计模式)都是通过JavaBeans实现的。
  JavaBeans不属于J2EE概念范畴中,如果一个JavaBeans对象被Web技术(也就是Jsp/Servlet)调用,那么JavaBeans就运行在J2EE的Web容器中;如果它被EJB调用,它就运行在EJB容器中。
  EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务、安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系统。
  至此,JavaBeans组件发展到EJB后,并不是说以前的那种JavaBeans形式就消失了,这就自然形成了两种JavaBeans技术:EJB和POJO,POJO完全不同于EJB概念,指的是普通JavaBeans,而且这个JavaBeans不依附某种框架,或者干脆可以说:这个JavaBeans是你为这个应用程序单独开发创建的。
  J2EE应用系统开发工具有很多:如JBuilder、Eclipse等,这些IDE首先是Java开发工具,也就是说,它们首要基本功能是可以开发出JavaBeans或Java class,但是如果要开发出J2EE系统,就要落实到要么是Web技术或EJB技术,那么就有可能要一些专门模块功能(如eclipse需要lomboz插件),最重要的是,因为J2EE系统区分为容器和应用两个部分,所以,在任何开发工具中开发J2EE都需要指定J2EE容器。
  J2EE容器分为WEB容器和EJB容器,Tomcat/Resin是Web容器;JBoss是EJB容器+Web容器等,其中Web容器直接使用Tomcat实现的。所以你开发的Web应用程序可以在上面两种容器运行,而你开发的Web+EJB应用则只可以在JBoss服务器上运行,商业产品Websphere/Weblogic等和JBoss属于同一种性质。
  J2EE容器也称为J2EE服务器,大部分时它们概念是一致的。
  如果你的J2EE应用系统的数据库连接是通过JNDI获得,也就是说是从容器中获得,那么你的J2EE应用系统基本与数据库无关,如果你在你的J2EE应用系统耦合了数据库JDBC驱动的配置,那么你的J2EE应用系统就有数据库概念色彩,作为一个成熟需要推广的J2EE应用系统,不推荐和具体数据库耦合,当然这其中如何保证J2EE应用系统运行性能又是体现你的设计水平了。
  衡量J2EE应用系统设计开发水平高低的标准就是:解耦性;你的应用系统各个功能是否能够彻底脱离?是否不相互依赖,也只有这样,才能体现可维护性、可拓展性的软件设计目标。
  为了达到这个目的,诞生各种框架概念,J2EE框架标准将一个系统划分为WEB和EJB主要部分,当然我们有时不是以这个具体技术区分,而是从设计上抽象为表现层、服务层和持久层,这三个层次从一个高度将J2EE分离开来,实现解耦目的。
  因此,我们实际编程中,也要将自己的功能向这三个层次上靠,做到大方向清楚,泾渭分明,但是没有技术上约束限制要做到这点是很不容易的,因此我们还是必须借助J2EE具体技术来实现,这时,你可以使用EJB规范实现服务层和持久层,Web技术实现表现层;
  EJB为什么能将服务层从Jsp/Servlet手中分离出来,因为它对JavaBeans编码有强制的约束,现在有一种对JavaBeans弱约束,使用Ioc模式实现的(当然EJB 3.0也采取这种方式),在Ioc模式诞生前,一般都是通过工厂模式来对JavaBeans约束,形成一个服务层,这也是是Jive这样开源论坛设计原理之一。
  由此,将服务层从表现层中分离出来目前有两种可选架构选择:管理普通JavaBeans(POJO)框架(如Spring、JdonFramework)以及管理EJB的EJB框架,因为EJB不只是框架,还是标准,而标准可以扩展发展,所以,这两种区别将来是可能模糊,被纳入同一个标准了。 但是,个人认为:标准制定是为某个目的服务的,总要牺牲一些换取另外一些,所以,这两种架构会长时间并存。
  这两种架构分歧也曾经诞生一个新名词:完全POJO的系统也称为轻量级系统(lightweight),其实这个名词本身就没有一个严格定义,更多是一个吸引人的招牌,轻量是指容易学习容易使用吗?按照这个定义,其实轻量Spring等系统并不容易学习;而且EJB 3.0(依然叫EJB)以后的系统是否可称为轻量级了呢?
  前面谈了服务层框架,使用服务层框架可以将JavaBeans从Jsp/Servlet中分离出来,而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离,这部分JavaBeans主要负责显示相关,一般是通过标签库(taglib)实现,不同框架有不同自己的标签库,Struts是应用比较广泛的一种表现层框架。
  这样,表现层和服务层的分离是通过两种框架达到目的,剩余的就是持久层框架了,通过持久层的框架将数据库存储从服务层中分离出来是其目的,持久层框架有两种方向:直接自己编写JDBC等SQL语句(如iBatis);使用O/R Mapping技术实现的Hibernate和JDO技术;当然还有EJB中的实体Bean技术。
  持久层框架目前呈现百花齐放,各有优缺点的现状,所以正如表现层框架一样,目前没有一个框架被指定为标准框架,当然,表现层框架现在又出来了一个JSF,它代表的页面组件概念是一个新的发展方向,但是复杂的实现让人有些忘而却步。
  在所有这些J2EE技术中,虽然SUN公司发挥了很大的作用,不过总体来说:网络上有这样一个评价:SUN的理论天下无敌;SUN的产品用起来撞墙;对于初学者,特别是那些试图通过或已经通过SUN认证的初学者,赶快摆脱SUN的阴影,立即开溜,使用开源领域的产品来实现自己的应用系统。
  最后,你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现,基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。
  还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解,那么域建模提供了一种比较切实可行的正确理解业务需求的方法,相关详细知识可从UML角度结合理解。
  当然,如果你想设计自己的行业框架,那么第一步从设计模式开始吧,因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法,当你学会了系统基本单元JavaBean或类之间解耦时,那么系统模块之间的解耦你就可能掌握,进而你就可以实现行业框架的提炼了,这又是另外一个发展方向了。
  以上理念可以总结为一句话:J2EE开发三件宝: Domain Model(域建模)、patterns(模式)和framework(框架)。
  推荐一套高质量的J2EE开源系统: JPestore

2009年1月17日星期六

一张专家推荐的最健康的作息时间表

许多人都希望拥有健康的生活方式。据英国媒体报道,来自英美的健康专家指出:人们只需要每天做一些小小的改变,生活就会发生很大的不同。专家根据人体在不同时段的特点,教人们如何简单拥有健康完美的一天。
7:30:起床。英国威斯敏斯特大学的研究人员发现,那些在早上5:22—7:21分起床的人,其血液中有一种能引起心脏病的物质含量较高,因此,在7:21之后起床对身体健康更加有益。打开台灯。“一醒来,就将灯打开,这样将会重新调整体内的生物钟,调整睡眠和醒来模式。”拉夫堡大学睡眠研究中心教授吉姆·霍恩说。喝一杯水。水是身体内成千上万化学反应得以进行的必需物质。早上喝一杯清水,可以补充晚上的缺水状态。


7:30—8:00:在早饭之前刷牙。“在早饭之前刷牙可以防止牙齿的腐蚀,因为刷牙之后,可以在牙齿外面涂上一层含氟的保护层。要么,就等早饭之后半小时再刷牙。”英国牙齿协会健康和安全研究人员戈登·沃特金斯说。


8:00—8:30:吃早饭。“早饭必须吃,因为它可以帮助你维持血糖水平的稳定,”伦敦大学国王学院营养师凯文·威尔伦说。早饭可以吃燕麦粥等,这类食物具有较低的血糖指数。


8:30—9:00:避免运动。来自布鲁奈尔大学的研究人员发现,在早晨进行锻炼的运动员更容易感染疾病,因为免疫系统在这个时间的功能最弱。步行上班。马萨诸塞州大学医学院的研究人员发现,每天走路的人,比那些久坐不运动的人患感冒病的几率低25%。


9:30:开始一天中最困难的工作。纽约睡眠中心的研究人员发现,大部分人在每天醒来的一两个小时内头脑最清醒。


10:30:让眼睛离开屏幕休息一下。如果你使用电脑工作,那么每工作一小时,就让眼睛休息3分钟。

11:00:吃点水果。这是一种解决身体血糖下降的好方法。吃一个橙子或一些红色水果,这样做能同时补充体内的铁含量和维生素C含量。

13:00:在面包上加一些豆类蔬菜。你需要一顿可口的午餐,并且能够缓慢地释放能量。“烘烤的豆类食品富含纤维素,番茄酱可以当作是蔬菜的一部分。”维伦博士说。


14:30—15:30:午休一小会儿。雅典的一所大学研究发现,那些每天中午午休30分钟或更长时间,每周至少午休3次的人,因心脏病死亡的几率会下降37%。


16:00:喝杯酸奶。这样做可以稳定血糖水平。在每天三餐之间喝些酸牛奶,有利于心脏健康。


17:00—19:00:锻炼身体。根据体内的生物钟,这个时间是运动的最佳时间,舍菲尔德大学运动学医生瑞沃·尼克说。


19:30:晚餐少吃点。晚饭吃太多,会引起血糖升高,并增加消化系统的负担,影响睡眠。晚饭应该多吃蔬菜,少吃富含卡路里和蛋白质的食物。吃饭时要细嚼慢咽。


21:45:看会电视。这个时间看会儿电视放松一下,有助于睡眠,但要注意,尽量不要躺在床上看电视,这会影响睡眠质量。


23:00:洗个热水澡。“体温的适当降低有助于放松和睡眠。”拉夫堡大学睡眠研究中心吉姆·霍恩教授说。


23:30:上床睡觉。如果你早上7点30起床,现在入睡可以保证你享受8小时充足的睡眠。

2009年1月16日星期五

一个月30万的诱惑 老股民16年炒股经验总结

  巴菲特价值投资理念对当代股民影响非常大,如今刚刚“新鲜出炉”的股民嘴上都会说,“我是抱着价值投资的心态来炒股,投机的事我不做”。但是,一些上世纪90年代入市的老股民就未必这样想。
  杨怀彬有着16年的炒股经验,经历过大赚,也遭遇过巨亏,而他就一直坚持着盯庄的炒股模式。
  一个月30万的诱惑
推荐阅读
理财专家访谈:如何积极应对2009理财市场
09年稳赚不赔的理财术
王刚:95%的人收藏着95%的赝品
十二星座2009年理财建议
09年理财:如何找出最牛投资品种
08年百姓身边的九种股民(图)
2008八大最牛财经人物(图)
2008年全球最为离谱的辞职(图)
  上世纪80年代,国内掀起了一股“下海”潮,当时的杨怀彬正值而立,想闯出一番事业,集结了一帮朋友南下做生意去了。在深圳的10年中,杨怀彬积累了一些财富。“1992年,一次巧合的机遇,误入了股市。”杨怀彬如此形容他进入股市的原因。
  不过,每个人面对新事物都要交学费,“尤其是炒股这点事,而我也不例外。”杨怀彬说。当时的股票不多,他刚一入市就买了深宝安,没多久深宝安连续下挫,他的几万元本钱一下子就亏掉了35%。以后一年多都处于交学费的状态,亏多赚少,但可喜的是,亏的比例越来越小了。
  到了1994年,杨怀彬通过旭飞投资和开元控股(000516,股吧)在一个月的时间里赚了超过30万,这些都是当时流通股份比较小的小盘股,小盘股资金比较容易撬动,当时这些股票几乎每天的涨幅都超过10%。靠着这些股票,杨怀彬赚到了股市第一桶金。
  小盘股成主力
  之后的几年,杨怀彬仿佛进入了一个谷底,盈亏一直在10%之间徘徊,但在2001年开始的B股行情中,杨怀彬又大赚了一笔。2001年春节,杨怀彬套现了一部分A股的资金逐步进入B股,尽管后来证监会紧急叫停B股爆炒,但那一个月的时间,他已经赚了30%。这一年,他的股票市值达到了300万元。
  而在A股市场4年多的熊市中,杨怀彬一直处于盈利状态。“主要原因,还是我跟着庄家一直炒小盘股。”2004年,杨怀彬在10元附近买入亨通光电(600487,股吧),这只股票从9元已经开始启动。“能够确定它进入上升通道,因为这是新股,盘子又小,加上前期的走势,我觉得肯定有人在坐庄,所以我就全仓介入,买了10万股。”最后,该股一直涨到14元,这一役,杨怀彬就赚了40多万元。
  这之后,杨怀彬就一直以次新股、小盘股为目标。几年下来资金总额翻了好几番。
  盯庄要止损
  总结自己16年的炒股经验,杨怀彬说:“我也知道价值投资的好处,可是那样的投资方式不是我擅长的,如果从短线操作来说,盯庄是最有效的方式,也是我所熟悉的。而揣测那些庄家的心理,寻找盘子小,且没有炒作过的股票,最符合他们的胃口。”但杨怀彬也表示,并不是所有的人都能够熟练运用这样的策略,“短线、盯庄一定要懂得止损”。
  “最近大市的剧烈震荡,就是庄家已经介入,他们想要出货,就一定会拉高,他们想要抢筹就一定会砸盘。有庄就一定有钱赚,只是看谁的策略更高明而已,而且我相信A股市场还是会向上走的。”杨怀彬自信地说。

java中的split使用的是正则表达式

听说这个split方法比那个StringTokenizer效率高一点,今天刚好用上,就拿来试试,没有想到一试就出问题了,把折分结果打在控制台上,结果居然是空的,我要折分的字符串是“5#1|7#2|11#3”刚用这里str.split("|")时就出问题了,看了下面这篇文章,将其改为str.split("\\|")就OK了,这个|在正则表达式中也是个特殊字符。回头还得弄弄正则表达式了。
public static void main(string[] args) {
string value = "192.168.128.33";
string[] names = value.split(".");
for (int i = 0; i < names.length; i++) {
system.out.println(names[i]);
}

}
运行结果:

对,没看错!没有任何输出!
让我们来看看 split 方法的方法签名吧:
public string[] split(string regex)
这里的参数的名称是 regex ,也就是 regular expression (正则表达式)。这个参数并不是一个简单的分割用的字符,而是一个正则表达式

,看了 split 方法的实现代码就更坚定了我们的信心:
public string[] split(string regex, int limit) {
return pattern.compile(regex).split(this, limit);
}
split 的实现直接调用的 matcher 类的 split 的方法。读者已经知道,“ . ”在正则表达式中有特殊的含义,因此我们使用的时候必须进行转义。
public static void main(string[] args) {
string value = "192.168.128.33";
//注意要加\\,要不出不来,yeah
string[] names = value.split("\\.");
for (int i = 0; i < names.length; i++) {
system.out.println(names[i]);
}

}

2009年1月15日星期四

Java连接Oracle数据库的各种方法

java与oracle的接口:
  在数据库中运行JAVA可以说是ORACLE8i的最令人激动的新特性。在你创建的使用ORACLE8i 数据库的应用程序中,你可以使用与JAVA有关的新特征,轻松的将程序发布到INTERNET或INTRANET上。 ADD1a+gR
   y zlEpG;N
  Methods for Using Java in ORACLE ojGAm@'s2
   ~GX* C{cq
  大家都知道JAVA在跨平台开发与INTERNET开发中已经比较流行,ORACLE8i及以后的版本中都包含了对在数据库中运行JAVA的扩展支持,这里有两种方法可以使用: +brLiL}Y
   wG}\$NM#
  JDBC:与ODBC类似, JDBC 提供了一个驱动接口使你可以在JAVA程序中访问数据库。注:JDBC驱动内嵌在数据库中虚拟机中。 KgsV868
   $$\Nc3
  SQLJ:是一个JAVA预编译器,它可以将内嵌的SQL语句转化为JAVA语句.SQLJ的使用与运行机理与其它ORACLE的与编译器(如Pro*C,Pro*COBOL)类似。实际上,为了使我们形象的记住SQLJ提供的功能,我们也可以直接将SQLJ改名为Pro*Java。 p~a#RO#6
   QG'6vbN
  将JAVA集成到数据库中是双向的。也就是说你可以在JAVA中调用SQL与PL/SQL,也可以在SQL与PL/SQL中调用JAVA。JAVA程序可以直接通过JDBC驱动调用SQL与PL/SQL,反过来,你也可以在SQL与PL/SQL中直接调用JAVA。在数据库中,JAVA命名空间直接映射到数据库模式的命名空间中,这样可以方便JAVA的存取与调用。数据库同时提供扩展的DDL语句,通过这些语句,你可以象创建一个存储过程一样在数据中创建内嵌的JAVA程序。 nXL-_6p
   mD#NK1. ~B
  Features of ORACLE JDBC Drivers Ys%"h{z29
   zvv+b>W"f
  在ORACLE8i中有三种类型的JDBC驱动,他们都使用相同的 syntax, APIs, and Oracle extensions,以使JAVA代码在robust clients、Web-based Java applets, and Java stored procedures之间保持轻便灵活:三种类型如下: 2=&VKw&
  1.JDBC OCI: 此驱动类似于传统的ODBC 驱动。因为它需要Oracle Call Interface and Net8,所以它需要在运行使用此驱动的JAVA程序的机器上安装客户端软件 A x.YJ/n-
  2.JDBC Thin: 这种驱动一般用在运行在WEB浏览器中的JAVA程序。它不是通过OCI or Net8,而是通过Java sockets进行通信 ,因此不需要在使用JDBC Thin的客户端机器上安装客户端软件。 U3a,: Dn
  3.JDBC KPRB: 这种驱动由直接存储在数据库中的JAVA程序使用,如Java Stored Procedures 、triggers、Database JSP's。It uses the default/ current database session and thus requires no additional database username, password or URL. J_\{fI]l
   8w(CTv
  如何配置使JAVA可以通过Oracle JDBC Drivers连接到数据库:1.安装Sun JDK.  7:a5grj 32
  2. 修改PATH环境变量,使其指向JDK的bin目录 zPT* T-2
  3. 设置CLASSPATH环境变量,使其指向正确的JDK的lib及oracle的JDBC接口。 HJ&"NgL9@
  CLASSPATH = ".;????" bTpkUvam
  3. 运行"java –version" ,验证java的版本。 }FHagj~y
   :$E?HI 'E
  如何在不同的操作系统上根据接口类型设置客户端: =BtC1wL
  对JDBC THIN接口: 1ID!qz6W
  在windows与unix下的设置方法一样: 9%7*~bW_
  1.根据jdk的版本,只需要将classesxx.zip拷贝到指定的目录,不需要安装Oracle Client。在装完数据库后,该文件会在$ORACLE_HOME/jdbc/lib目录下。2.设置CLASSPATH,使其包含上面的classesxx.zip 3(3 EoUj
  3.根据需要,拷贝oracle的其它zip文件并设置CLASSPATH pNQBz]G)
   &c3'yu
  对JDBC OCI接口: pc kI 
  Fow Windows: ^BHPb1oT
  1.安装Oracle Client. b~KsX(]
  2.根据jdk的版本,设置CLASSPATH,使其包含正确的classesxx.zip ygvFKneOdm
  3.根据需要设置CLASSPATH,使其指向Oracle的其它zip文件 }dJ}@1
  4.设置PATH,使其包含$ORACLE_HOME\bin目录 enq?Vx `
   o" gw#w
  For unix: ^FHD5.7)b
  1.安装Oracle Client. uNvU)]t
  2.根据jdk的版本,设置CLASSPATH,使其包含正确的classesxx.zip 5d[,?I8v
  3.根据需要设置CLASSPATH,使其指向Oracle的其它zip文件 3bQE;
  4.设置LD_LIBRARY_PATH,使其包含$ORACLE_HOME/lib目录 R$s( qz
   M^ 7L
  备注: `I A`' c
  classesxx.zip一般在ORACLE_HOME\jdbc\lib目录下。 `p{d`j6
   +p`j}AQ ]
     在ORACLE_HOME\jdbc\lib目录下的与Oracle JDBC Drives驱动有关的文件的解释: vT/uE[}Kq
   - classes12.zip !q6 fe:
    Classes for use with JDK 1.2.x. It contains the JDBC driver r& j V!u
    classes except classes necessary for NLS support in Object and uXJDF3jD}
    Collection types. }ofbQ,
   ZpI Bt_V
   - nls_charset12.zip )jb 48E
    NLS classes for use with JDK 1.2.x. It contains classes necessary 4l27guy
    for NLS support in Object and Collection types. a+K%@Kh~
   <`,: ,"     - classes12_g.zip R8cS NXf{     Same as classes12.zip, except that classes were compiled with <`bJM]D-/     "javac -g". }(H&>f1z
   po<`Ev3C<   JDBC连接数据库的语法: Pk C- P d]   JDBC THIN: 5;lejPk    hBq4EzK    0m!`ki%    Code: [Copy to clipboard]  TJOC !QC w   Connection conn= *TZsN<>5
      DriverManager.getConnection +5BE5[T
       ("jdbc:oracle:thin:@dlsun511:1521:ora1","scott","tiger"); [-h#Ygg
                         u(d;9"I
              machine(ip@) : port# : sid  t+&-k,) 
   UAM%.;w
  JDBC OCI: lo/]0e.T
   Bz&,r +/
   Code: [Copy to clipboard]  ;"L#5P}
  Connection conn= 8Toz"^K]l
      DriverManager.getConnection [Uuu7Pc%
       ("jdbc:oracle:oci8[9]:@RAC","scott","tiger"); S!j+Hk
                   }Q@?z>I(@
                  Net Service qt)mh0t9
    #lJ^#
  JDBC THIN与JDBC THIN对比: >S='*
  相同之处: }(q+Z}T6X
     The JDBC Thin, JDBC OCI, and JDBC Server drivers all provide the same functionality. They all support the following standards and features: !Wx)MK&
      * JDBC 2.0 >5%rq2
      * Partial JDBC 3.0 (in JDBC driver version 9.2) 'z9;qm.{
      * the same syntax and APIs o{x,Znr9
      * the same Oracle extensions ;V)qa:H%Q
  主要是JDBC OCI 接口比JDBC THIN接口效率高! Ypjm, _rHV
   >5^s_1#i
  How does one connect with the JDBC Thin Driver? =C&iY!c8V
     The the JDBC thin driver provides the only way to access Oracle from the Web (applets). It is smaller and slower than the OCI drivers. (J)BrD>
  import java.sql.*; `kJOn}Y 
   ]M ov% !
   Code: [Copy to clipboard]  . hr4 X/W
  class dbAccess { {f*)pE
   public static void main (String args []) throws SQLException =r$[>F7c
   { t^2"S`G<     DriverManager.registerDriver ( F*qVzl}w      new oracle.jdbc.driver.OracleDriver() &wpXXu)<     ); S?[am8}    cJFe=(@3     Connection conn = DriverManager.getConnection hUXA=s      ("jdbc:oracle:thin:@dbhost:1521:ORA1", "scott", "tiger"); =,MJSpxt&              // @machine:port:SID,  userid, password M*/ 7fXg    gTD`?*!     Statement stmt = conn.createStatement(); %# Ju\     ResultSet rset = stmt.executeQuery ( ;j#HfsO      "select BANNER from SYS.V_$VERSION" 4 v2)CfmKs     ); CC~z4cm'     while (rset.next()) STcpxdGK       System.out.println (rset.getString(1));  // Print col 1 pl@x}U>de
    stmt.close(); \qf$ 
   } +tP5Rr~`
  } VAjy_%fR;
  How does one connect with the JDBC OCI Driver? B40=S~oon
     One must have Net8 (SQL*Net) installed and working before attempting to use one of the OCI drivers. ;$]p&NG
   [sl(,8!,
   a #Qb,Tq-
   Code: [Copy to clipboard]  >Aqn">*
  import java.sql.*; "'.fF e}C
  class dbAccess { %eXb x+5f
   public static void main (String args []) throws SQLException / 7[+,G
   { 4+Q<}ST     try { gvbsgo6a      Class.forName ("oracle.jdbc.driver.OracleDriver"); Iq!s5'8     } catch (ClassNotFoundException e) { n4>):n#
     e.printStackTrace(); {Q=n@Z5
    } 0e<4 conn =" DriverManager.getConnection">toS6DS
      ("jdbc:oracle:oci8:@ORA1", "scott", "tiger"); P8 /k*}
         // or oci9 @Service, userid, password  1a(vH7
    Statement stmt = conn.createStatement(); -g9'o!=A
    ResultSet rset = stmt.executeQuery ( 1{y* U@
     "select BANNER from SYS.V_$VERSION" !RS(F j =(
    ); FG{t/^Dr
    while (rset.next()) CDKMW8\
     System.out.println (rset.getString(1)); // Print col 1 Z+ai;, >
    stmt.close(); 9%8, A'~
   } frj!  D0
  } Ov"4^S
  How does one connect with the JDBC KPRB Driver? ] CWg{&
     One can obtain a handle to the default or current connection (KPRB driver) by calling the OracleDriver.defaultConenction() method. Please note that you do not need to specify a database URL, username or password as you are already connected to a database session. Remember not to close the default connection. Closing the default connection might throw an exception in future releases of Oracle. Y@&O(Dg{
  import java.sql.*; 9sK`vnE^
   N.KaFe'Pa
   vc
   public static void main (String args []) throws SQLException + 5d;vcB=I
   { ?#p[:[iq
    Connection conn = (new )]}+tI+!
     oracle.jdbc.driver.OracleDriver()).defaultConnection(); TplHvoi
   f_a));@
    Statement stmt = conn.createStatement(); 3E:d_ ]NM
    ResultSet rset = stmt.executeQuery ( aC~hz.3$
     "select BANNER from SYS.V_$VERSION" yh164M
    );

2009年1月12日星期一

C# 读写 Oracle BLOB 数据

using System;
using System.Data.OracleClient;
using System.IO;

namespace fenghua.Data.Oracle
{
///
/// Class1 的摘要说明。
///

public class OracleLobData
{
private OracleConnection conn;
public OracleLobData()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

/*
* 在调用此函数之前需要写插入一个字符串到 BLOB 中比如:
* Select some data.
* Table Schema:
* "CREATE TABLE tablewithlobs (a int, b BLOB, c CLOB, d NCLOB)";
* "INSERT INTO tablewithlobs values (1, 'AA', 'AAA', N'AAAA')";
* 否则程序会在 OracleLob tempLob = reader.GetOracleLob(0) 处出错。
*/
///
/// 文件写入到 Oracle Blob 字段中。
///

/// id 值
/// 文件名
/// id 键
/// blob 键
/// 表名
public void WriteBlob(int idData, string fileName, string id, string blob, string tableName)
{
string connString = "server=oratest;User ID=kttest;Password=test";
using(conn = new OracleConnection(connString))
{
try
{
conn.Open();
OracleCommand cmd = conn.CreateCommand();

// 利用事务处理(必须)
OracleTransaction transaction = cmd.Connection.BeginTransaction();
cmd.Transaction = transaction;

// 获得 OracleLob 指针
cmd.CommandText = "select " + blob + " from " + tableName + " where " + id + " = " + idData + " FOR UPDATE";
OracleDataReader reader = cmd.ExecuteReader();
using(reader)
{
//Obtain the first row of data.
reader.Read();
//Obtain a LOB.
OracleLob tempLob = reader.GetOracleLob(0);

// 将文件写入 BLOB 中
FileStream fs = new FileStream(fileName,FileMode.Open);
tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);
int length = 10485760;
byte[] Buffer = new byte[length];
int i;
while((i = fs.Read(Buffer,0,length)) > 0)
{
tempLob.Write(Buffer,0,i);
}
fs.Close();
tempLob.EndBatch();
cmd.Parameters.Clear();
}
// 提交事务
transaction.Commit();
}
catch(Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
}
}

///
/// 读取 Oracle Blob 到文件中。
///

/// id 值
/// 文件名
/// id 键
/// blob 键
/// 表名
public void ReadBlob(int idData,string fileName, string id, string blob, string tableName)
{
string connString = "server=oratest;User ID=kttest;Password=test";
using(conn = new OracleConnection(connString))
{
try
{
conn.Open();
OracleCommand cmd = conn.CreateCommand();

// 利用事务处理(必须)
OracleTransaction transaction = cmd.Connection.BeginTransaction();
cmd.Transaction = transaction;

// 获得 OracleLob 指针
string sql = "select " + blob + " from " + tableName + " where " + id + " = " + idData;
cmd.CommandText = sql;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
OracleLob tempLob = dr.GetOracleLob(0);
dr.Close();

// 读取 BLOB 中数据,写入到文件中
FileStream fs = new FileStream(fileName,FileMode.Create);
int length = 1048576;
byte[] Buffer = new byte[length];
int i;
while((i = tempLob.Read(Buffer,0,length)) > 0)
{
fs.Write(Buffer,0,i);
}
fs.Close();
tempLob.Clone();
cmd.Parameters.Clear();

// 提交事务
transaction.Commit();
}
catch(Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
}
}
}
}

能否给一个解决问题的方法

补充一下新增blob型数据
///
/// 文件写入到 Oracle Blob 字段中(新增)。
///

/// 主键列值,tableName表中新增BLOB类型数据的主键值
/// 文件名
/// 主键列名,tableName表中新增BLOB类型数据的主键
/// blobColName列名
/// 表名
public void WriteBlob(string fileName, string tableName, string blobColName, string key, int keyData)
{
string strSql = "select * from " + tableName;
OracleConnection conn = new OracleConnection(connString);
OracleDataAdapter da = new OracleDataAdapter(strSql, conn);
OracleCommandBuilder CB = new OracleCommandBuilder(da);
DataSet ds = new DataSet(tableName);
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;

FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Read);
byte[] BlobData = new byte[fs.Length];
fs.Read(BlobData, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
da.Fill(ds, tableName);

DataRow newRow;
newRow = ds.Tables[tableName].NewRow();
newRow[key] = keyData;
newRow[blobColName] = BlobData;
ds.Tables[tableName].Rows.Add(newRow);
da.Update(ds, tableName);

}

请修改原来方法为UpdateBlob(...)

在C#中存储Blob类型的数据,

其中:id代表关键字段id,file_name代表文件名 
bb_images代表目录对象,目录对象创建如下
create directory bb_images as ‘d:\kk’;
在C#中的代码部分与
http://www.cnblogs.com/surprise/archive/2005/04/19/140461.html雷同,在这里就不必多说了
优点:无论多大的图片都能处理,速度上也非常快
缺点:只能存储数据库本地的图片
⑶ 不用储存过程的方式
原代码ConsoleApplication2.rar (推荐,在我们公司项目中就用到了)
优点:解决了所有以上的缺点
缺点:破坏了项目的层次感

3.最后介绍读取Blob数据项方式
原代码WebImage.rar 读取图片的方式比较简单,首先把Blob从数据库中读取出来,接着生成图片格式,最后输出图片就行。

将全角的变为半角

将全角的变为半角
string s="GBJ1—86";
char[] c=s.ToCharArray();
for (int i=0;i {
byte[] b=System.Text.Encoding.Unicode.GetBytes(c,i,1);
if (b.Length==2)
{
if (b[1]==255)
{
b[0]=(byte)(b[0]+32);
b[1]=0;
c[i]=System.Text.Encoding.Unicode.GetChars(b)[0];
}
}
}
//半角
string news=new string(c);

面向服务开发的七项原则

1. 动态的服务替代了静态的组件
构建一个Web服务不仅仅是像传统的组件开发期望的那样创建具有特殊功能的软件。一个W
eb服务的Web服务描述语言(WSDL)文件动态地描述了Web服务的功能。所以,开发人员只
需要指出在哪里找到WSDL文件,这样调用Web服务的软件在运行时就可以找到对服务功能的
描述。该原则要求在运用Web服务的系统中显示逻辑层同商业逻辑层和持久(persistence
)逻辑层分离开。当开发人员构建一个Web服务时,他们可能不知道那个服务是如何被调用
的、或者Web服务使用者的用户界面将是怎样的。一个Web服务架构师不能将商业逻辑和显
示逻辑结合起来。

2. 服务呈现(Exposure)和响应(Reflection)替代了传统的系统集成
当今的系统架构师根据系统级的需求来集成项目。架构师计划各种组件应该如何集成。作
为这种top-down方法的替代,面向服务的开发采用了一种bottom-up的方法。在任何系统结
构形成前,系统中的每个组件都呈现成一个Web服务。然后,每个服务(查询一个服务自己
的功能)给外部系统提供它们访问服务所需要的信息。

在构建一个系统时,Web服务架构师首先考虑系统的需求,并进行服务装配。在服务装配过
程中,架构师访问服务的动态描述,它们只代表了实际的API的一部分。然后,架构师确定
系统的结构,即使在运行前,单独的组件及其接口并没有被完全地描述。

3. 为广泛的适用性编写代码替代了为可重用性编写代码
为可重用性编写代码是面向对象编程的一个重要的特点。实际上,对开发人员来说,编写
可重用的代码可能比为单独用途的应用程序编写代码更具挑战性。因此,灵活的软件方法
(如Extreme Programming(XP))就避开了可重用性。在XP中,如果外来的功能进入到代
码中,那么开发人员就重新编写、或重构(refactor)代码,直到它尽可能地简单。

虽然重构可以形成一些重用的方法,因为最终代码满足很多情况,但这种方法同传统的为
可重用性编写的代码不同,因为它的目的是创建灵活的和广泛适用的代码。重用性和广泛
适用性的代码的区别是很小的,但它们却是面向服务的开发过程的本质。最好的方法就是
把面向服务开发的结构性原则同灵活的开发原则结合起来。

4. 特别的升级替代了单独的组件(Disruptive)升级
模块性是面向对象编程的另一个基本的原则。如果系统是模块化的,那么构成系统的单独
的组件就可以被升级或替代,而不影响系统的其它部分。不幸的是,在如今的企业组件结
构中,模块性在很大程度上是个谜。
当然,问题是在一个复杂的系统中替换或升级组件并不像人们期望地那样简单或便宜。We
b服务呈现了动态服务描述,而不是简单地呈现APIs。如果根本的API发生改变,服务描述自动调整,系统的其它组件在运行时可以根据变化做出调整。

5. 可扩展性采用Bottom-Up式设计过程,而不是Top-Down式设计过程
可扩展性比随处添加一个附加的服务器要复杂多了。首先,架构师要预测使用模式并为负
载平衡和故障转移(failover)做计划。然后他们必须设计系统以避免出现瓶颈问题。这
种用于可扩展性的方法就是top-down式的,因为它首先从企业级角度考虑了潜在的系统交
易模式。

然而,在一个完全实现了的具有Web服务的环境中,可扩展性应该是以bottom-up模式来处
理的。架构师可以设置UDDI注册来提供备份Web服务清单,主要是为了可扩展性和故障转移 。如果一个系统遇到未预料到的交易,它就可以自动在注册文件中找到备份服务,得到它们的服务描述,然后很快绑定到附加的服务上。

6. 平台依赖性为平台不相关性让步
企业系统开发的基于组件的方法就是在平台上构建组件,并通过它们的接口来呈现它们的
功能。本质上,组件就像踢球的足球运动员,平台就像球场。因此,如果俩个球员在不同
的球场,那么他们之间的交流就会很困难。
面向服务的方法采用的观点是,整个软件环境是由动态描述的服务组成的,在需要的时候
,它们可以很快地被找到并调用。要注意,平台在任何时候都不会很快被抛弃,这是很重
要的。Java 2 Platform、Enterprise Edition(J2EE)和.NET将转移到用户所处的外围,
这些平台提供了必要的底层框架来编写和运行Web服务,并提供了用户需要访问那些服务的接口支持。面向服务的争论的中心议题只会是Web服务,它们是以XML为基础的。

7. 软件的松藕合(Federation)替代了紧藕合(Dictatorship)
Web服务的松散藕合解决了带有严格APIs的基于组件的结构中紧密藕合的许多问题。但是,
面向服务开发的松散藕合原则对企业软件的传统的、紧密藕合的世界还有更深远的影响。
运用松散藕合,架构师就可以通过组合Web服务的动态描述的集合来创建企业软件。软件供应商将提供服务的松散藕合。随着时间的推移,由于开发人员进行了特别的升级,构成这
种企业包的各种Web服务将一天一天地发生变化,通过根据需要装配另外的Web服务,在运 行时,系统就会不断发生变化。

C#应用:获取cpu序列号,硬盘ID,网卡MAC地址

private void GetInfo()
{
string cpuInfo = "";//cpu序列号
ManagementClass cimobject = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = cimobject.GetInstances();
foreach(ManagementObject mo in moc)
{
cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
Response.Write ("cpu序列号:"+cpuInfo.ToString ());
}
//获取硬盘ID
String HDid;
ManagementClass cimobject1 = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc1 = cimobject1.GetInstances();
foreach(ManagementObject mo in moc1)
{
HDid = (string)mo.Properties["Model"].Value;
Response.Write ("硬盘序列号:"+HDid.ToString ());
}

//获取网卡硬件地址
9558821702001755616

ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc2 = mc.GetInstances();
foreach(ManagementObject mo in moc2)
{
if((bool)mo["IPEnabled"] == true)
Response.Write("MAC address\t{0}"+mo["MacAddress"].ToString());
mo.Dispose();
}
}

.Net中如何操作IIS

前天在csdn看到有人问如何使用C#操作IIS,很久之前就想写一写这方面的文章,这次正好毕业做完有点时间,我就有空静下心来写这一文章。在写本文前,我首先花了一天的时间写了一操作IIS的类(编译后也可以称之组件),进一步简化了操作,源代码下一篇将全部贴出来,还有一些测试程序,有兴趣的朋友可以到这里下载。

.Net中实际上已经为我们在这方面做得很好了。FCL中提供了不少的类来帮助我们完成这项工作,让我们的开发工作变非常简单和快乐。编程控制IIS实际上很简单,和ASP一样,.Net中需要使用ADSI来操作IIS,但是此时我们不再需要GetObject这个东东了,因为.Net为我们提供了更加强大功能的新东东。

System.DirectoryServices命名空间中包括了些强大的东东--DirectoryEntry,DirectoryEntries,它们为我们提供了访问活动目录的强大功能,在这些类允许我们操作IIS、LDAP、NDS以及WinNT,功能很强大的吧:)

不过我们此处只谈IIS的控制,一般来说,我们操作IIS一般都是对虚拟目录的操作,因此我将此列为主要的内容来讲。

首先我们要搞清楚IIS的层次结构的问题,下面是我从国外找来的一张图,很好的解释了IIS的层次结构:



为了搞清楚IIS的控制语法,我们就必须搞清上图,了解IIS元数据(Metabase)的层次结构。图中的每一个节点称之Key,而每个Key可以包含一个或多个值,这些值就是我们说的属性(properties),IIS元数据中的Key与IIS中的元素是相符的,因此元数据中的属性值的设定是会影响IIS中的设置。这就是我们编程的基本思路和核心。

另外还要了解一下Schema这个概念。它表示IIS中构架的名称,即可以理解IIS元数据中Key的类型,具体点说就是指每个结点的类型。我们知道,IIS中有虚拟目录,普通目录,以及文件这些东东,而这些都属于IIS的元素,区分的他们的标帜就是Schema。比如虚拟目录的Schema就是"IIsVirtualDir",普通目录就是"IIsWebDir"。这样我们添加、删除目录时,IIS就知道我们添加的是虚拟目录还是普通目录。

创建虚拟目录

DirectoryEntry是.Net给我们的一大礼物,他的名字我们就知道他的功能--目录入口。使用过ADSI的人都知道操作IIS,WinNT这些时,我们还需要提供他们的Path,操作IIS时,这个Path的格式为:

IIS://ComputerName/Service/Website/Directory

ComputerName:即操作的服务器的名字,可以是名字也可以是IP,经常用的就是localhost
Service:即操作的服务器,IIS中有Web,也有FTP,还有SMTP这些服务,我们主要是操作IIS的Web功能,因此此处就是"W3SVC",如果是FTP则应是"MSFTPSVC"
WebSite:一个IIS服务中可以包括很多的站点,这个就用于设置操作的站点。他的值是一个数字,默认是1,表示缺省站点,如果有其它,则从1开始依次类推。
Directory:不用说,即操作的目录名称,一个站点一般顶层目录为"ROOT",其它目录则是他的孩子(Child)。
首先我们获取一个站点的顶层目录(根目录):

DirectoryEntry rootfolder = new DirectoryEntry("IIS://localhost/W3SVC/1/ROOT");

如果我们创建这个对象是没有发生异常,则表示这个目录是真实存在的。

下面我们来添加新的虚拟目录,比如我们要加的是"Aspcn":

DirectoryEntry newVirDir = rootfolder.Children.Add("Aspcn","IIsWebVirtualDir");
newVirDir.Invoke("AppCreate",true);
newVirDir.CommitChanges();
rootfolder.CommitChanges();
 

创建目录的思路很简单,即在根目录的子集(rootfolder.Children)中再添加一条记录,这里使用的是DirectoryEntries类中的Add方法,它返回的是一个DirectoryEntry,表示新加入的目录,第一个参数是虚拟目录的名字,第二个则是Schema的类名以表明我们加入的目录类型。然后再使用DirectoryEntry的Invoke方法,调用ADSI中的"AppCreate"方法将目录真正创建(似乎不走这一步也可以创建目录成功,但是为了保险起见,大家还是用吧),最后便是依次调用新、根目录的CommitChanges方法,确认此次操作。

在创建新目录时,我们也可以同时给这个目录的属性赋值,但是我的实战经验告诉我,最好不要这样做,如果创建时就赋值,将有很多属性不能赋值成功,比如重要的表示真实目录的Path属性。因此飞刀建议大家最好是先创建目录,然后再赋值,即更新目录信息。

更新虚拟目录

相信大家对IIS都比较熟悉,了解IIS中一些重要的设置,如可读(AccessRead)、可写(AccessWrite)、可执行(AccessExecute)等。这些都可通过对DirectoryEntry的Properties属性集合的赋值来实现。赋值可以通过两种方式来完成:

第一种是调用Properties集合的Add方法,如:

dir.Properties["AccessRead"].Add(true);

第二种是对第一个索引值赋值:

dir.Properties["AccessRead"][0] = true;

这两种方法都是可行的。具体是要看你的喜好了。

在进行赋值之前我们还是要确定要要赋值的目标吧:)这里我们使用DirectoryEntries类的Find方法,如:

DirectoryEntry de = rootfolder.Children.Find("Aspcn","IIsVirtualDir");

找到了,我们就可以赋值了。赋值时一定要好好看看啊,虚拟目录的属性值可以超多,一查一大堆。。:(太多了,飞刀我也不重复了,大家去微软的站点上查:)

比较常用的有:AccessRead,AccessWrite,AccessExecute,AccessScript,DefaultDoc,EnableDefaultDoc,Path

删除虚拟目录

删除虚拟目录的方法也很简单,就是找到你要删除的虚拟目录,然后调用AppDelete方法。

DirectoryEntry de = rootfolder.Children.Find("Aspcn","IIsVirtualDir");
de.Invoke("AppDelete",true);
rootfolder.CommitChanges();
 

还有一种方法,就是调用Root目录的Delete方法。

object[] paras = new object[2];
paras[0] = "IIsWebVirtualDir"; //表示操作的是虚拟目录
paras[1] = "Aspcn";
rootfolder.Invoke("Delete",paras);
rootfolder.CommitChanges();

喜欢哪一种就看编程习惯了:))

关于我写的类

我写的那个类库,将这些进一步简化了。只需要调用一下Connect()方法,就可直接操作Create,Delete方法了,程序可以进一步简化,并且支持批量操作。
///***********************************************************
///************** IIS控制管理类 1.0 Beta

using System;
using System.Data;
using System.DirectoryServices;
using System.Collections;
namespace Aspcn.Management
{
///
/// IISManager 的摘要说明。
///

public class IISManager
{
//定义需要使用的
private string _server,_website;
private VirtualDirectories _virdirs;
protected System.DirectoryServices.DirectoryEntry rootfolder;
private bool _batchflag;
public IISManager()
{
//默认情况下使用localhost,即访问本地机
_server = "localhost";
_website = "1";
_batchflag = false;
}
public IISManager(string strServer)
{
_server = strServer;
_website = "1";
_batchflag = false;
}
///
/// 定义公共属性
///


//Server属性定义访问机器的名字,可以是IP与计算名
public string Server
{
get{ return _server;}
set{ _server = value;}
}
//WebSite属性定义,为一数字,为方便,使用string
//一般来说第一台主机为1,第二台主机为2,依次类推
public string WebSite
{
get{ return _website; }
set{ _website = value; }
}

//虚拟目录的名字
public VirtualDirectories VirDirs
{
get{ return _virdirs; }
set{ _virdirs = value;}
}
///
///定义公共方法
///


//连接服务器
public void Connect()
{
ConnectToServer();
}
//为方便重载
public void Connect(string strServer)
{
_server = strServer;
ConnectToServer();
}
//为方便重载
public void Connect(string strServer,string strWebSite)
{
_server = strServer;
_website = strWebSite;
ConnectToServer();
}
//判断是否存这个虚拟目录
public bool Exists(string strVirdir)
{
return _virdirs.Contains(strVirdir);
}
//添加一个虚拟目录
public void Create(VirtualDirectory newdir)
{
string strPath = "IIS://" + _server + "/W3SVC/" + _website + "/ROOT/" + newdir.Name;
if(!_virdirs.Contains(newdir.Name) || _batchflag )
{
try
{
//加入到ROOT的Children集合中去
DirectoryEntry newVirDir = rootfolder.Children.Add(newdir.Name,"IIsWebVirtualDir");
newVirDir.Invoke("AppCreate",true);
newVirDir.CommitChanges();
rootfolder.CommitChanges();
//然后更新数据
UpdateDirInfo(newVirDir,newdir);
}
catch(Exception ee)
{
throw new Exception(ee.ToString());
}
}
else
{
throw new Exception("This virtual directory is already exist.");
}
}
//得到一个虚拟目录
public VirtualDirectory GetVirDir(string strVirdir)
{
VirtualDirectory tmp = null;
if(_virdirs.Contains(strVirdir))
{
tmp = _virdirs.Find(strVirdir);
((VirtualDirectory)_virdirs[strVirdir]).flag = 2;
}
else
{
throw new Exception("This virtual directory is not exists");
}
return tmp;
}

//更新一个虚拟目录
public void Update(VirtualDirectory dir)
{
//判断需要更改的虚拟目录是否存在
if(_virdirs.Contains(dir.Name))
{
DirectoryEntry ode = rootfolder.Children.Find(dir.Name,"IIsWebVirtualDir");
UpdateDirInfo(ode,dir);
}
else
{
throw new Exception("This virtual directory is not exists.");
}
}
 
//删除一个虚拟目录
public void Delete(string strVirdir)
{
if(_virdirs.Contains(strVirdir))
{
object[] paras = new object[2];
paras[0] = "IIsWebVirtualDir"; //表示操作的是虚拟目录
paras[1] = strVirdir;
rootfolder.Invoke("Delete",paras);
rootfolder.CommitChanges();
}
else
{
throw new Exception("Can't delete " + strVirdir + ",because it isn't exists.");
}
}
//批量更新
public void UpdateBatch()
{
BatchUpdate(_virdirs);
}
//重载一个:-)
public void UpdateBatch(VirtualDirectories vds)
{
BatchUpdate(vds);
}
 
///
///私有方法
///


//连接服务器
private void ConnectToServer()
{
string strPath = "IIS://" + _server + "/W3SVC/" + _website +"/ROOT";
try
{
this.rootfolder = new DirectoryEntry(strPath);
_virdirs = GetVirDirs(this.rootfolder.Children);
}
catch(Exception e)
{
throw new Exception("Can't connect to the server ["+ _server +"] ...",e);
}
}
//执行批量更新
private void BatchUpdate(VirtualDirectories vds)
{
_batchflag = true;
foreach(object item in vds.Values)
{
VirtualDirectory vd = (VirtualDirectory)item;
switch(vd.flag)
{
case 0:
break;
case 1:
Create(vd);
break;
case 2:
Update(vd);
break;
}
}
_batchflag = false;
}
//更新东东
private void UpdateDirInfo(DirectoryEntry de,VirtualDirectory vd)
{
de.Properties["AnonymousUserName"][0] = vd.AnonymousUserName;
de.Properties["AnonymousUserPass"][0] = vd.AnonymousUserPass;
de.Properties["AccessRead"][0] = vd.AccessRead;
de.Properties["AccessExecute"][0] = vd.AccessExecute;
de.Properties["AccessWrite"][0] = vd.AccessWrite;
de.Properties["AuthBasic"][0] = vd.AuthBasic;
de.Properties["AuthNTLM"][0] = vd.AuthNTLM;
de.Properties["ContentIndexed"][0] = vd.ContentIndexed;
de.Properties["EnableDefaultDoc"][0] = vd.EnableDefaultDoc;
de.Properties["EnableDirBrowsing"][0] = vd.EnableDirBrowsing;
de.Properties["AccessSSL"][0] = vd.AccessSSL;
de.Properties["AccessScript"][0] = vd.AccessScript;
de.Properties["DefaultDoc"][0] = vd.DefaultDoc;
de.Properties["Path"][0] = vd.Path;
de.CommitChanges();
}

//获取虚拟目录集合
private VirtualDirectories GetVirDirs(DirectoryEntries des)
{
VirtualDirectories tmpdirs = new VirtualDirectories();
foreach(DirectoryEntry de in des)
{
if(de.SchemaClassName == "IIsWebVirtualDir")
{
VirtualDirectory vd = new VirtualDirectory();
vd.Name = de.Name;
vd.AccessRead = (bool)de.Properties["AccessRead"][0];
vd.AccessExecute = (bool)de.Properties["AccessExecute"][0];
vd.AccessWrite = (bool)de.Properties["AccessWrite"][0];
vd.AnonymousUserName = (string)de.Properties["AnonymousUserName"][0];
vd.AnonymousUserPass = (string)de.Properties["AnonymousUserName"][0];
vd.AuthBasic = (bool)de.Properties["AuthBasic"][0];
vd.AuthNTLM = (bool)de.Properties["AuthNTLM"][0];
vd.ContentIndexed = (bool)de.Properties["ContentIndexed"][0];
vd.EnableDefaultDoc = (bool)de.Properties["EnableDefaultDoc"][0];
vd.EnableDirBrowsing = (bool)de.Properties["EnableDirBrowsing"][0];
vd.AccessSSL = (bool)de.Properties["AccessSSL"][0];
vd.AccessScript = (bool)de.Properties["AccessScript"][0];
vd.Path = (string)de.Properties["Path"][0];
vd.flag = 0;
vd.DefaultDoc = (string)de.Properties["DefaultDoc"][0];
tmpdirs.Add(vd.Name,vd);
}
}
return tmpdirs;
}

}
///
/// VirtualDirectory类
///

public class VirtualDirectory
{
private bool _read,_execute,_script,_ssl,_write,_authbasic,_authntlm,_indexed,_endirbrow,_endefaultdoc;
private string _ausername,_auserpass,_name,_path;
private int _flag;
private string _defaultdoc;
///
/// 构造函数
///

public VirtualDirectory()
{
SetValue();
}
public VirtualDirectory(string strVirDirName)
{
_name = strVirDirName;
SetValue();
}
private void SetValue()
{
_read = true;_execute = false;_script = false;_ssl= false;_write=false;_authbasic=false;_authntlm=false;
_indexed = false;_endirbrow=false;_endefaultdoc = false;
_flag = 1;
_defaultdoc = "default.htm,default.aspx,default.asp,index.htm";
_path = "C:\\";
_ausername = "";_auserpass ="";_name="";
}
///
///定义属性,IISVirtualDir太多属性了
///我只搞了比较重要的一些,其它的大伙需要的自个加吧。
///


public int flag
{
get{ return _flag;}
set{ _flag = value;}
}
public bool AccessRead
{
get{ return _read;}
set{ _read = value;}
}
public bool AccessWrite
{
get{ return _write;}
set{ _write = value;}
}
public bool AccessExecute
{
get{ return _execute;}
set{ _execute = value;}
}
public bool AccessSSL
{
get{ return _ssl;}
set{ _ssl = value;}
}
public bool AccessScript
{
get{ return _script;}
set{ _script = value;}
}
public bool AuthBasic
{
get{ return _authbasic;}
set{ _authbasic = value;}
}
public bool AuthNTLM
{
get{ return _authntlm;}
set{ _authntlm = value;}
}
public bool ContentIndexed
{
get{ return _indexed;}
set{ _indexed = value;}
}
public bool EnableDirBrowsing
{
get{ return _endirbrow;}
set{ _endirbrow = value;}
}
public bool EnableDefaultDoc
{
get{ return _endefaultdoc;}
set{ _endefaultdoc = value;}
}
public string Name
{
get{ return _name;}
set{ _name = value;}
}
public string Path
{
get{ return _path;}
set{ _path = value;}
}
public string DefaultDoc
{
get{ return _defaultdoc;}
set{ _defaultdoc = value;}
}
public string AnonymousUserName
{
get{ return _ausername;}
set{ _ausername = value;}
}
public string AnonymousUserPass
{
get{ return _auserpass;}
set{ _auserpass = value;}
}
}
///
/// 集合VirtualDirectories
///


public class VirtualDirectories : System.Collections.Hashtable
{
public VirtualDirectories()
{
}
//添加新的方法
public VirtualDirectory Find(string strName)
{
return (VirtualDirectory)this[strName];
}
}
}

在 ASP.NET 中使用 HTTP 模块实现 Intercepting Filter

实现策略
Intercepting Filter (截取筛选器)模式的 ASP.NET 实现是该模式中所描述的事件驱动型筛选器的一个例子。ASP.NET 提供了应用程序可以在请求处理期间钩挂的一系列事件。这些事件保证了请求的状态。各个筛选器都是通过一个 HTTP 模块实现的。HTTP 模块是一个实现 IHttpModule 接口并确定应该何时调用筛选器的类。ASP.NET 包括一组可由应用程序使用的 HTTP 模块。例如,SessionStateModule 由 ASP.NET 提供,以便向应用程序提供会话状态服务。您可以创建自己的自定义 HTTP 模块,以便根据应用程序的需要筛选请求或响应。
编写自定义 HTTP 模块的一般过程是:
实现 IHttpModule 接口。
处理 Init 方法并注册到您需要的事件。
处理事件。
如果必须清理,也可以选择实现 Dispose 方法。
在 web.config 文件中注册模块。
事件
下表显示了可以使用 ASP.NET 截取的、在处理请求期间产生的事件。所有事件都是按照发生的顺序列出的。
第一个列表显示了处理请求之前产生的事件。
BeginRequest. 此事件标志着这是一个新请求;每个请求都必须产生该事件。
AuthenticateRequest. 此事件标志着所配置的身份验证机制已经验证了请求。附加到此事件可向筛选器确保请求已通过身份验证。
AuthorizeRequest. 与 AuthenticateRequest 一样,此事件标志着现在请求在处理过程中又前进了一步,并且请求已经得到授权。
ResolveRequestCache. 输出缓存模块使用此事件来简化对已经缓存的请求所进行的处理。
AcquireRequestState. 此事件标志着应该获得各个请求状态。
PreRequestHandlerExecute. 此事件标志着请求处理程序将要执行。这是在调用此请求的 HTTP 处理程序之前您可以参与的最后一个事件。
下一个列表显示了处理请求之后产生的事件。这些事件是按照发生的顺序列出的:
PostRequestHandlerExecute. 此事件标志着 HTTP 处理程序已经完成了对请求的处理。
ReleaseRequestState. 此事件标志着应该存储请求状态,因为应用程序已经完成了对请求的处理。
UpdateRequestCache. 此事件标志着代码处理已完成,可以将文件添加到 ASP.NET 缓存中。
EndRequest. 此事件标志着已完成对请求的所有处理。这是应用程序结束时所调用的最后一个事件。
此外,以下三个请求处理前事件可以按不确定顺序引发:
PreSendRequestHeaders.此事件标志着 HTTP 头将要发送给客户端。因此可以在发送之前添加、删除或修改头信息。
PreSendRequestContent. 此事件标志着内容将要发送给客户端。这为发送之前修改内容提供了一个机会。
Error. 此事件标志着有未处理的异常。
下面的示例说明了请求在通过了 ASP.NET 运行库的身份验证之后是如何被截取的。对名为 UserLogger 的示例模块进行初始化时,它将把一个名为 OnAuthenticate 的成员函数连接到 AuthenticateRequest 事件。每次对新的请求进行身份验证时,都会调用 OnAuthenticate 函数。在本示例中,OnAuthenticate 函数将把通过了身份验证的用户的名称记录到 Intercepting Filter 模式应用程序事件日志中。using System;
using System.Web;
using System.Security.Principal;
using System.Diagnostics;
public class UserLogModule : IHttpModule
{
private HttpApplication httpApp;
public void Init(HttpApplication httpApp)
{
this.httpApp = httpApp;
httpApp.AuthenticateRequest += new EventHandler(OnAuthentication);
}
void OnAuthentication(object sender, EventArgs a)
{
HttpApplication application = (HttpApplication)sender;
HttpResponse response = application.Context.Response;
WindowsIdentity identity =
(WindowsIdentity)application.Context.User.Identity;
LogUser(identity.Name);
}
private void LogUser(String name)
{
EventLog log = new EventLog();
log.Source = "Intercepting Filter Pattern";
log.WriteEntry(name,EventLogEntryType.Information);
}
public void Dispose()
{}
}
示例模块必须添加到 web.config 文件中,以便 ASP.NET 运行库能够识别该模块。下面是为 UserLogModule 示例模块进行了更改的配置文件:


返回页首
示例
下面是内置在 Microsoft .NET 中的截取筛选器的示例:
DefaultAuthenticationModule. 此筛选器确保 Authentication 对象出现在 HttpContext 对象中。
FileAuthorizationModule. 此筛选器验证远程用户是否拥有访问所请求的文件时所需的 Microsoft Windows NT? 权限。
FormsAuthenticationModule. 此筛选器使 ASP.NET 应用程序能够使用窗体验证。
PassportAuthenticationModule.此筛选器提供了包装 PassportAuthentication 服务以便进行 Passport 身份验证的包装器。
SessionStateModule. 此筛选器为应用程序提供会话状态服务。
UrlAuthorizationModule. 此筛选器提供基于 URL 的授权服务,以便允许或拒绝对指定 URL 进行访问。
WindowsAuthenticationModule. 此筛选器使 ASP.NET 应用程序能够使用 Microsoft Windows? 或 Internet 信息服务 (IIS) 的身份验证机制。
返回页首
测试考虑事项
如果没有 ASP.NET 运行库,就不可能测试 HTTP 模块。因此,必须采用稍微不同的实现策略,尽可能将更多的功能与实现 IHttpModule 接口的类分开。在前面的示例中,记录用户名的代码不需要 ASP.NET 运行库。此功能可以放在名为 UserLog 的类中,该类独立于 ASP.NET。实现 IHttpModule 接口的 UserLogAdapter 类可以使用 UserLog 类。这样,其他类就可以使用 UserLog 类,而且,您也可以在没有 ASP.NET 环境的情况下对它进行测试。以下是前面所描述的同一功能,但它允许在没有 ASP.NET 运行库的情况下对记录功能进行测试:using System;
using System.Diagnostics;
public class UserLog
{
public static void Write(String name)
{
EventLog log = new EventLog();
log.Source = "Intercepting Filter Pattern";
log.WriteEntry(name,EventLogEntryType.Information);
}
}
using System;
using System.Web;
using System.Security.Principal;
public class UserLogAdapter
{
private HttpApplication httpApp;
public void Init(HttpApplication httpApp)
{
this.httpApp = httpApp;
httpApp.AuthenticateRequest += new EventHandler(OnAuthentication);
}
void OnAuthentication(object sender, EventArgs a)
{
HttpApplication application = (HttpApplication)sender;
HttpResponse response = application.Context.Response;
WindowsIdentity identity =
(WindowsIdentity)application.Context.User.Identity;
UserLog.Write(identity.Name);
}
public void Dispose()
{}
}

C#操作Excel文件(读取Excel,写入Excel)

看到论坛里面不断有人提问关于读取excel和导入excel的相关问题。闲暇时间将我所知道的对excel的操作加以总结,现在共享大家,希望给大家能够给大家带了一定的帮助。另外我们还要注意一些简单的问题1.excel文件只能存储65535行数据,如果你的数据大于65535行,那么就需要将excel分割存放了。2.关于乱码,这主要是字符设置问题。
1.加载Excel(读取excel内容)返回值是一个DataSet
//加载Excel
public static DataSet LoadDataFromExcel(string filePath)
{
try
{
string strConn;
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=False;IMEX=1'";
OleDbConnection OleConn = new OleDbConnection(strConn);
OleConn.Open();
String sql = "SELECT * FROM [Sheet1$]";//可是更改Sheet名称,比如sheet2,等等
OleDbDataAdapter OleDaExcel = new OleDbDataAdapter(sql, OleConn);
DataSet OleDsExcle = new DataSet();
OleDaExcel.Fill(OleDsExcle, "Sheet1");
OleConn.Close();
return OleDsExcle;
}
catch (Exception err)
{
MessageBox.Show("数据绑定Excel失败!失败原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
}
2.写入Excel内容,参数:excelTable是要导入excel的一个table表

alimama_pid="mm_10249644_1605763_5027492";
alimama_type="f";
alimama_sizecode ="tl_1x5_8";
alimama_fontsize=12;
alimama_bordercolor="FFFFFF";
alimama_bgcolor="FFFFFF";
alimama_titlecolor="0000FF";
alimama_underline=0;
alimama_height=22;
alimama_width=0;


public static bool SaveDataTableToExcel(System.Data.DataTable excelTable, string filePath)
{
Microsoft.Office.Interop.Excel.Application app =
new Microsoft.Office.Interop.Excel.ApplicationClass();
try
{
app.Visible = false;
Workbook wBook = app.Workbooks.Add(true);
Worksheet wSheet = wBook.Worksheets[1] as Worksheet;
if (excelTable.Rows.Count > 0)
{
int row = 0;
row = excelTable.Rows.Count;
int col = excelTable.Columns.Count;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
string str = excelTable.Rows[i][j].ToString();
wSheet.Cells[i + 2, j + 1] = str;
}
}
}
int size = excelTable.Columns.Count;
for (int i = 0; i < size; i++)
{
wSheet.Cells[1, 1 + i] = excelTable.Columns[i].ColumnName;
}
//设置禁止弹出保存和覆盖的询问提示框
app.DisplayAlerts = false;
app.AlertBeforeOverwriting = false;
//保存工作簿

alimama_pid="mm_10249644_1605763_5027492";
alimama_type="f";
alimama_sizecode ="tl_1x5_8";
alimama_fontsize=12;
alimama_bordercolor="FFFFFF";
alimama_bgcolor="FFFFFF";
alimama_titlecolor="0000FF";
alimama_underline=0;
alimama_height=22;
alimama_width=0;


wBook.Save();
//保存excel文件
app.Save(filePath);
app.SaveWorkspace(filePath);
app.Quit();
app = null;
return true;
}
catch (Exception err)
{
MessageBox.Show("导出Excel出错!错误原因:" + err.Message, "提示信息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
finally
{
}
}

.NET程序加解密技术基础

一、什么是.NET?
微软官方给出的定义是:.NET框架是支持生成和运行下一代运行程序内部Windows的组件。同时,.NET还有很多别的平台上的实现,只要符合计算机制造商协会规定的公共语言基础框架CLI的平台,我们都可以实现.NET的平台。比如说MONO,还有SSCLI。
在本文中,我们主要的议题还是围绕在第一点,Windows平台的应用。
首先,.NET是一个面向对象的框架。
其次,它是个将软件部署和版本控制冲突最小化的代码执行环境。我讲这些涉及到以后加解密中间需要的一些特点。
第三,它是一个可提高代码执行安全性的代码执行环境,这点后面也会提到。.NET生成中间代码以后,通过即时编译,会比JAVA运行速度快一些。
最后一点,确保基于.NET的框架代码可以和任何代码集成,这是最大的特色,就是编程语言的统一。讲了这么多,还是我们来谈一谈从加解密的角度看,.NET是什么?
一句话,就是构建于操作系统之上的虚拟机。我们今天谈的.NET包含两个部分,一个是通用语言运行时,也就是CLR。
图1是一个Windows平台上的.NET框架基本结构示意图,大家可以看到有很多各种不同的编程语言,经过中间整合为元数据,在底层Windows与应用程序中间最大的框就是.NET,两个部分,左边这块是CLR,是它的运行环境,右边是.NET的类库,结构就是这样。
图1 Windows系统上的.NET框架结构
二、加解密所关注的.NET带来的改变
1、PE文件结构的改变
.NET作为新的平台,肯定引进一些新的技术。我们讨论的是加解密,因此我们有关注的特殊点,第一是在PE结构上带来的一些改变,大家很清楚PE结构是Windows平台上可执行程序的结构,普通的PE文件保存的是机器指令的编码,图2是典型的普通的PE文件示意图。
图2 普通的PE文件
但是.NET下的PE文件,在.NET下叫程序集,其保存的是另外两种数据,叫元数据和MSIL,当然同时还保存其他的数据,但主要是元数据和MSIL,中间语言。
在.NET下,PE结构中改变最大的属于.text节,它包含.NET的基本结构和数据的比如说CLR头,一些输入表,元数据等,这是.NET对PE文件的最大的改变。
讲到这里引出.NET中一个非常重要的概念,元数据。什么是元数据?字典上解释为描述数据的数据,用在.NET上也是非常合适的。首先它本身就是一个数据,0101,第二它描述了.NET程序的全部信息,一个.NET程序想正常运行,必须是一个合法的.NET程序,必须包含合法完整的元数据。因此我们说.NET程序是自描述的,运行的时候,程序集本身包含了所有信息,不需要寻找别的依赖性的信息(比如注册表中)。
但是程序集的这种自描述的性质,使得反编译时的信息更加丰富,结合MSIL的特征,使得反编译的结果近似源代码。如图3所示,左边这张图是一个反编译的图,再看看点击的方法,所有的名称都被显示了出来。所以说元数据还是挺可怕的。
图3 程序集的这种自描述性质使得反编译时信息更加丰富,结合MSIL的特性,使得反编译结果近似原代码
下面简单介绍一下元数据的基本结构,元数据是以数据流的形式保存在文件中,各种有不同的形式,一个是堆,一个是表,流是统称,而堆和表是存在形式。
图4表示了.NET下的六个元数据堆,第二个流是Blob,所有二进制数据都保存在Blob中,第三个是GUID,每个程序集唯,这个比较简单。第四个流,US代表用户字符串,红色标示的是比较常见的,和加解密关系比较重要的,因为用户字符串中保存了比较关键的信息,。下一个#-,最重要的流,所有的堆存在于这个流中。
图4 .NET下的6个元数据堆
图5的倒数第二行介绍了所有的元数据堆,也就是.NET的元数据表,从00到44,大家看看这些名称基本上反映了.NET面向框架结构,基本上结构从名称中就可以看出来了。
图5 .NET的元数据表
2、统一了编程语言
第二个主要的变化是统一了编程语言。像我们编程做应用开发的时候,可以使用C++,C#或者其他语言,但是这些语言经过静态编译以后,统一到MSIL。
MSIL的特点,第一它是高级语言,面向对象的,比汇编高级很多。第二它是是基于堆栈的运行机制。来看一段示例代码(图6)。
图6 代码
第一行定义局部变量,名称为VAL,下面为MSIL指令。我们一句一句的看。首先初始堆栈为空,然后第三句,出栈,又入栈,然后10和1两个参数入栈,最后运算,结果入栈。这是MSIL最显著的特点,但是也给.NET加解密带来一个非常常用的操作,叫往复操作(round-tripping),中文我不太清楚,就是拿到一个.NET的PE文件,我们反编译成源文件,在源码上进行操作以后,通过框架提供的ilasm,再编译成可执行文件,只有通过元数据和MSIL可以实现这种操作。
3、程序运行方式的改变
加解密所关注.NET的变化第三点我觉得是程序运行方式的改变。Windows不再直接负责程序的运行,而是由.NET框架进行管理。框架中JIT引擎负责在运行时将IL代码即时编译为本地汇编代码执行。.NET程序被称为托管程序,相反地,我们说的传统的Windows程序,就是非托管程序(或称为本地程序)。
下面简单介绍.NET的基本概念。
首先是我们常听到的程序集。程序集是.NET可执行程序的基本单元,程序集中间包含一个或多个模块,模块和程序集的区别是模块不含清单信息,所以模块是不能直接运行的,而程序集是可以的。在MSIL中编程时,程序集没有扩展名。
第二个是类型。面向对象大家非常熟悉了,差别不是很大,方法也是一样。类型有很多成员,其中最重要的是方法,因为加解密关注方法中的关键代码,所以方法是非常重要的成员。
然后是标识,就是怎么定位.NET中每一个元数据,在MSIL是一个32位的值,类似AABBBBBB的形式。比如方法元数据在元数据表中排第七个,从零开始计数的话,就是06,Main方法为第一个方法,排第一,因此Main方法的元数据标识就0x06000001。再比如某字符串为0X70000001,就是这样一个简单的标识。
最后,有一个概念叫签名,签名就是存储在Blob中的一段二进制数据,它的作用是描述特定元数据的性质。.NET下共有六个表包含签名项。
程序集的运行方式,即时编译,JIT,这是.NET运行可执行程序的基本方式,也就是在需要运行的时候,将对应的IL代码编译为本机指令,传入JIT中的是IL代码,导出的是本机代码。所以,部分加密软件通过挂钩JIT进行加解密操作。
以上讲解的是.NET程序加解密技术的一些基础知识。.NET加解密是一个很有意思的方向,.NET加解密技术的发展使得保护方式多样化,强度远大于诞生初期,已经不能单纯地从托管的层次解决了。

本文主要内容整理自软件安全专家单海波先生在2008中国软件安全峰会(www.sinoit.org.cn)上的演讲。

百度将打造首本数据新闻图书 09年初上市发行

1月9日消息,腾讯科技从接近百度的知情人士处获悉,百度正在联合出版社着手策划一系列图书,并将很快推向市场。 据传,此番百度所策划出版的这套书,在内容方面将另辟蹊径,绝非市面上常见的公司及领导人物传记、产业技术描绘或管理类图书,而作者则为“全体中国网民”。 对这一消息,百度相关负责人未置可否。腾讯科技获悉,百度正在策划筹备的这套图书,将围绕“年度记忆”展开,内容偏向于年度纪实。“百度是全球最大的中文搜索引擎,每天接受来自全球138个国家的上亿次访问和查询,拥有海量的用户数据资源,这是任何一个企业或者机构都无法比拟的。因此,由百度来策划和出版这样一本新闻纪实类书籍,并不奇怪。”业内专家推测认为,百度正在策划的这套纪实类图书,“很可能将围绕其全年搜索数据展开,并成为中国第一本数据新闻图书。”专家指出,随着互联网向人民生活的渗透,作为互联网入口的搜索引擎已经逐渐成为社会发展的“留声机”,每一次搜索,都忠实地反映着中国网民的思想、关注度以及社会热点。梳理和归纳之后,就是一部真实生动的社会历史。而据知情人士透露,这套别具一格的图书目前已经进入出版流程的最后环节,极有可能于2009年初上市发行。

08年JavaScript总结

“2008年真是太棒了,不仅仅是因为很多厉害的人物在使用JavaScript和新的canvans元素,浏览器厂商也在竞争,试图超越对方在JavaScript方面的表现,这都证明了JavaScript的重要性。以下是我的总结:Games对于JavaScript游戏来说这一年很伟大。使用DHTML和基于Canvas的游戏似乎有能力来接管Flash的一些领域。许多经典的游戏都被重新的设计:Super Mario , Pac-ManYUI pacman:很酷的YUI JavaScript库游戏), Breakout , Space Invaders , Bomberman T&C Surf Designs

还有很多在经典的旧游戏上加入了他们的新思想:Matt Hackett创作的 Spacius , Mark Wilcox 创作的 Invaders from Mars , VertigoProject创作的 RedLine RacingTetris game

我们甚至还看到了一些角色扮演的游戏:Andrew Wooldridge创造的Tombs of Asciiroth CanvasQuest ,Pierre Chassaing创造的ProtoRPG。 虽然他们大多数都只是试用版或演示,但是我相信有一天他们会变的相当的酷。


2008年还出现了一些有趣的JavaScript / DHTML游戏库,最突出的就是GameJs GameJS:超酷的Canvas游戏库)和GameQuery ,后者为jQuery库的扩展。

最后这个很特别, DEFENDER of the favicon,它将旧游戏Defender压缩到了只有16x16的空间。

Demos越来越多的浏览器开始支持canvas元素,也就是说,在绘制动态图形方面我们又多了一种选择。有人制作出了一个小型简单的演示 ,用于展示Canavs的能力,但是有些人在这个基础上又向前迈了一步,就像 Matt Westcott制作的Antisocial demo

今年的大忙人Mathieu 'p01' Henri制作了很多小应用,使用一行代码就能做相当酷的事:Rubber effectTunnex Mars ,他们都在256个字节以内!

Mathieu Henri 利用canvas元素,在20 lines 比赛 中创造出了惊人的效果: Dynamic HypnoglowTwinkleHypno Trip Down the Fractal Rug 。这次比赛的优秀作品还有:colliding balls 3D cube effect dynamically generated BMP flames

Asylum inmates在20-line games的比赛中创建了:Lunar Lander a Boulderdash cloneWolfenstein 3D

3D
canvas元素只支持2D图像,但是这并不代表他不能制作出3D的效果:basic 3D cubes , texturing experimentsJavaScript/Canvas 3D engines很酷的 3D Canvas 演示)。还有许多3D的东西在Nihilogic上。

EmulationMatt Westcott创造的JSSpeccy the ZX Spectrum emulator 。James Urquhart 创造的SCUMM interpreter

我个人最喜欢的是JavaScript AGI interpreter

Graphics最令人印象深刻的是John Resig将Processing语言加入JavaScript-Processing.js ,Aza Raskin创建了Algorithm Ink。Eitan Suez将Turtle,字符串图像变成工具转换成JavaScript版,TurtleJS

Audio
Cameron Adams 创建了一个有趣的JavaScript实例:JS-909JS-909:一个不使用Flash的有趣打鼓机器),这是一个打鼓机器,能够演奏声音而不使用Flash,也不使用任何库,声音由标签引入。sk89q 创造的sine waveform generator ,动态生成和播放WAV文件。

其他你能使用CSS做些什么了?是不是只是为了您的文字样式?显然不是,Román Cortés证明了这一点,他创造一个 Simpson的形象 ,但这需要你拥有足够的CSS技巧。另外,Ernest Delgado 提供了一个汽车导航的演示 (canvas:驾驶导航)。

最后一个类似于我们小时候玩的积木,Cubescape ,可选择不同的颜色。

我在此许愿,希望2009年的javaScript能更酷!”

08年JavaScript总结

“2008年真是太棒了,不仅仅是因为很多厉害的人物在使用JavaScript和新的canvans元素,浏览器厂商也在竞争,试图超越对方在JavaScript方面的表现,这都证明了JavaScript的重要性。以下是我的总结:Games对于JavaScript游戏来说这一年很伟大。使用DHTML和基于Canvas的游戏似乎有能力来接管Flash的一些领域。许多经典的游戏都被重新的设计:Super Mario , Pac-ManYUI pacman:很酷的YUI JavaScript库游戏), Breakout , Space Invaders , Bomberman T&C Surf Designs

还有很多在经典的旧游戏上加入了他们的新思想:Matt Hackett创作的 Spacius , Mark Wilcox 创作的 Invaders from Mars , VertigoProject创作的 RedLine RacingTetris game

我们甚至还看到了一些角色扮演的游戏:Andrew Wooldridge创造的Tombs of Asciiroth CanvasQuest ,Pierre Chassaing创造的ProtoRPG。 虽然他们大多数都只是试用版或演示,但是我相信有一天他们会变的相当的酷。


2008年还出现了一些有趣的JavaScript / DHTML游戏库,最突出的就是GameJs GameJS:超酷的Canvas游戏库)和GameQuery ,后者为jQuery库的扩展。

最后这个很特别, DEFENDER of the favicon,它将旧游戏Defender压缩到了只有16x16的空间。

Demos越来越多的浏览器开始支持canvas元素,也就是说,在绘制动态图形方面我们又多了一种选择。有人制作出了一个小型简单的演示 ,用于展示Canavs的能力,但是有些人在这个基础上又向前迈了一步,就像 Matt Westcott制作的Antisocial demo

今年的大忙人Mathieu 'p01' Henri制作了很多小应用,使用一行代码就能做相当酷的事:Rubber effectTunnex Mars ,他们都在256个字节以内!

Mathieu Henri 利用canvas元素,在20 lines 比赛 中创造出了惊人的效果: Dynamic HypnoglowTwinkleHypno Trip Down the Fractal Rug 。这次比赛的优秀作品还有:colliding balls 3D cube effect dynamically generated BMP flames

Asylum inmates在20-line games的比赛中创建了:Lunar Lander a Boulderdash cloneWolfenstein 3D

3D
canvas元素只支持2D图像,但是这并不代表他不能制作出3D的效果:basic 3D cubes , texturing experimentsJavaScript/Canvas 3D engines很酷的 3D Canvas 演示)。还有许多3D的东西在Nihilogic上。

EmulationMatt Westcott创造的JSSpeccy the ZX Spectrum emulator 。James Urquhart 创造的SCUMM interpreter

我个人最喜欢的是JavaScript AGI interpreter

Graphics最令人印象深刻的是John Resig将Processing语言加入JavaScript-Processing.js ,Aza Raskin创建了Algorithm Ink。Eitan Suez将Turtle,字符串图像变成工具转换成JavaScript版,TurtleJS

Audio
Cameron Adams 创建了一个有趣的JavaScript实例:JS-909JS-909:一个不使用Flash的有趣打鼓机器),这是一个打鼓机器,能够演奏声音而不使用Flash,也不使用任何库,声音由标签引入。sk89q 创造的sine waveform generator ,动态生成和播放WAV文件。

其他你能使用CSS做些什么了?是不是只是为了您的文字样式?显然不是,Román Cortés证明了这一点,他创造一个 Simpson的形象 ,但这需要你拥有足够的CSS技巧。另外,Ernest Delgado 提供了一个汽车导航的演示 (canvas:驾驶导航)。

最后一个类似于我们小时候玩的积木,Cubescape ,可选择不同的颜色。

我在此许愿,希望2009年的javaScript能更酷!”

Google发现的十大真理

常常,一些很有价值的东西隐藏在不起眼或者说大家不注意的地方。Google的Ten Things就是如此。
1. 以用户为中心,其他一切纷至沓来。
2. 最好的方式是将一件事情做到极致。
3. 快比慢好。
4. 网络需要民主的作风。
5. 您不必坐在台式机前也能获得所需的答案。
6. 您可以通过正当途径赚钱。
7. 信息始终在不断地累加。
8. 对信息的需求超越了国界。
9. 没有西装革履也一样严肃认真。
10. 只是优秀还不够。
更多的说明还是请读原文
这些都是常识。但是,中国现在很多地方,缺乏或者说不容易实施的正是一些常识。
比如说第6点“通过正当途径赚钱”,这些年来,有多少公司是始终只靠正当途径赚钱的?去年,我们见过太多的公司因为不正当途径赚钱而身败名裂。三聚氰胺就不说了,百度小广告也不说了。就是整个网络媒体,能遵守版权法的可以说寥寥无几。我常常为查找某篇文章的原始出处而犯难,因为转载如海洋,而且几乎没有人给出起码的出处。更多的技术媒体是吃海外饭的,直接翻译就用,简单称之为“来自外媒”……
是的,我们把太多时间花在了没有意义的事情上,因此事事处处都显得技不如人。去年十一出游,我们在红色景区平型关,看到了缴获的日军武器,其中一门精致山炮令我们无不惊讶,那种做工,很难想象我们现在能否做得出来……

架构师书单 2nd Edition

为了2007年的目标,列了下面待读或重读的书单。 "其实中国程序员,现在最需要的是一张安静的书桌。",的确,中国架构师大多缺乏系统的基础知识,与其自欺欺人的宣扬"读书无用,重在实践变通,修身立命哲学书更重要",把大好时间用来追逐互联网上的片言只语,不如直面缺陷,系统的学习一次。
书单越读越薄,好书真的不多哇。
一、Software Architecture篇
这个领域没有什么"畅销书",可能读者中本来就是开发设计人员与项目经理占了多数,真正定位为架构师而且做的也是架构师工作的不多吧,你懂的尽是偏僻的人生。
《Software Architecture in Practice,2nd Edition--软件构架实践(第2版)》
第一版是第九届JOLT作品,一本被引用很多的架构书。
《Documenting Software Architectures --软件构架编档》
第13届JOLT大奖作品,捕获架构的过程,徐昊推荐。
《Applied Software Architecture --实用软件体系结构》
另一本被引用很多的架构之书。

二、UML 篇
UML、4+1视图始终是架构师界最通用的东西,寻找一种向世界妥协的方式。 1. 《UML Distilled 3rd》
没什么特别想推荐的UML工具书,选本最薄的吧。
2.《The Elements of UML 2.0 Style》
胜在没有同类书。
3.《UML和模式应用(第3版)--Applying UML and Patterns 3rd》 UML+RUP作的OOAD过程。
三、特定领域篇
开发人员有GOF23 Pattern,架构师同样也有架构师的Pattern。不同领域的架构师需要不同的知识。1. 公共领域《Domain-Specific Application Frameworks --特定领域应用框架:行业的框架体验》 ozzzzzz推荐,介绍了30个特定领域特定框架的设计。《Head First Design Patterns》 最好的GOF23经典设计模式阐释,适合被[GAMMA95]折磨的架构师拿来复习,中文版即将发行。 2. Java EE领域 《Patterns of Enterprise Application Architecture --企业应用架构模式》 Martin Fowler老书,企业应用各层上的模式。 《Effective Enterprise Java--中文版》 Neward, Ted作品,作者学贯东西(.Net与Java),像写Blog一样,每一页里面都有大量的信息。
可惜两本都比较旧了,没有新版。
3. EAI/SOA领域 《Enterprise Integration Patterns --企业集成模式:设计、构建及部署消息传递解决方案》
4. 网络与后台服务编程领域《Pattern-Oriented Software Architecture, Volume 2 --面向模式的软件体系结构 卷2:用于并发和网络化对象的模式》《Pattern-Oriented Software Architecture, Volume 3 --面向模式的软件体系结构卷3:资源管理模式》
著名的POSA2与POSA3。
四、闲书篇
《Code Complete 2 --代码大全2》 一本你教育小弟时的代言人。
《The Pragmatic Programmer --程序员修炼之道:从小工到专家》 一本你启发小弟的代言人。
《The Art of Unix Programming --UNIX编程艺术》

五、高效读书心得
刚好Head First系列开头都有一段教人如何读书的话,再加工整理如下:1.尽量阅读中文版 虽然有人英文很强,有的翻译很差,但AnyWay 中文阅读与理解的时间,略读与快速定位的速度还是要快一些。 2.即时批注、总结笔记与交流 虽然爱书,但发现最有效的读书方式还是不断的制造脂批本,读书时在重要的文字下划线,把自己的心得写在页旁。 在明天复习一次批注,最好可以有空重新整理笔记,或者拿来与人讨论。 3.大量思考或重复记忆 看书最郁闷的事情就是看完之后脑袋空空了。技术书还好点,虽然看的时候可能很辛苦,但就像学会了骑单车,之后再骑的时候总是会的;而偏设计与管理的书,最容易的事情就是看的时候很快,看完没什么留下到实践中。 所以,我们不能以看小说的速度来看设计书,要寻找思考的机会,思考是最好的记忆。 又或者,大量的重复记忆,重复多遍直到无意识的记忆。 4.人体工学 那些见缝插针的时间与地点不是看这个书单的好地方。 环境不要有电视,音乐等强输入源,而微风阳光鸟语等弱输入源则有助活跃大脑。 看书时大量的喝水。 如果发现自己的大脑已经疲累,已经在浮光掠影的翻看,就要休息。 留给大脑消化的时间,看完书不要接着看其他有难度的书或事情。