C#动态加载DLL

利用反射进行动态加载和调用.
Assembly ass=Assembly.LoadFrom(DllPath); //利用dll的路径加载,同时将此程序集所依赖的程序集加载进来,需后辍名.dll
Assembly.LoadFile 只加载指定文件,并不会自动加载依赖程序集.Assmbly.Load无需后辍名
加载dll后,需要使用dll中某类.
Type type=ass.GetType(“TypeName”);//利用类型的命名空间和名称获得类型
需要实例化类型,才可以使用,参数可以人为的指定,也可以无参数,静态实例可以省略
Object obj = Activator.CreateInstance(type,params[]);//利用指定的参数实例话类型
调用类型中的某个方法:
需要首先得到此方法
MethodInfo mi=type.GetMethod(“MehtodName”);//通过方法名称获得方法
然后对方法进行调用,多态性利用参数进行控制
mi.Invoke(obj,params[]);//根据参数直线方法,返回值就是原方法的返回值

一个C#睡前故事

从 前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺。但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的 工作进度,以防止他偷懒。但是彼得又不想让老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论何时,只要我的工作取得了一点进展我都会及时 让你知道。彼得通过周期性地使用“带类型的引用”(原文为:“typed reference” 也就是delegate??)“回调”他的老板来实现他的承诺,如下:

接口

现在,彼得成了一个特殊的人,他不但能容忍吝啬的老板,而且和他周围的宇宙也有了密切的联系,以至于他认为宇宙对他的工作进度也感兴趣。不幸的是,他必须也给宇宙添加一个特殊的回调函数Advise来实现同时向他老板和宇宙报告工作进度。彼得想要把潜在的通知的列表和这些通知的实现方法分离开来,于是他决定把方法分离为一个接口:

委托

不幸的是,每当彼得忙于通过接口的实现和老板交流时,就没有机会及时通知宇宙了。至少他应该忽略身在远方的老板的引用,好让其他实现了IWorkerEvents的对象得到他的工作报告。(”At least he'd abstracted the reference of his boss far away from him so that others who implemented the IWorkerEvents interface could be notified of his work progress” 原话如此,不理解到底是什么意思:))

他的老板还是抱怨得很厉害。“彼得!”他老板吼道,“你为什么在工作一开始和工作进行中都来烦我?!我不关心这些事件。你不但强迫我实现了这些方法,而且还在浪费我宝贵的工作时间来处理你的事件,特别是当我外出的时候更是如此!你能不能不再来烦我?”

于是,彼得意识到接口虽然在很多情况都很有用,但是当用作事件时,“粒度”不够好。他希望能够仅在别人想要时才通知他们,于是他决定把接口的方法分离为单独的委托,每个委托都像一个小的接口方法:

静态监听者

这样,彼得不会再拿他老板不想要的事件来烦他老板了,但是他还没有把宇宙放到他的监听者列表中。因为宇宙是个包涵一切的实体,看来不适合使用实例方法的委托(想像一下,实例化一个“宇宙”要花费多少资源…..),于是彼得就需要能够对静态委托进行挂钩,委托对这一点支持得很好:

事件

不幸的是,宇宙太忙了,也不习惯时刻关注它里面的个体,它可以用自己的委托替换了彼得老板的委托。这是把彼得的Worker类的的委托字段做成public的一个无意识的副作用。同样,如果彼得的老板不耐烦了,也可以决定自己来激发彼得的委托(真是一个粗鲁的老板):

彼得不想让这些事发生,他意识到需要给每个委托提供“注册”和“反注册”功能,这样监听者就可以自己添加和移除委托,但同时又不能清空整个列表也不能随意激发彼得的事件了。彼得并没有来自己实现这些功能,相反,他使用了event关键字让C#编译器为他构建这些方法:

彼得知道event关键字在委托的外边包装了一个property,仅让C#客户通过+= 和 -=操作符来添加和移除,强迫他的老板和宇宙正确地使用事件。

收获所有结果

到这时,彼得终于可以送一口气了,他成功地满足了所有监听者的需求,同时避免了与特定实现的紧耦合。但是他注意到他的老板和宇宙都为它的工作打了分,但是他仅仅接收了一个分数。面对多个监听者,他想要“收获”所有的结果,于是他深入到代理里面,轮询监听者列表,手工一个个调用:

异步通知:激发 & 忘掉

同时,他的老板和宇宙还要忙于处理其他事情,也就是说他们给彼得打分所花费的事件变得非常长:

很不幸,彼得每次通知一个监听者后必须等待它给自己打分,现在这些通知花费了他太多的工作事件。于是他决定忘掉分数,仅仅异步激发事件:

异步通知:轮询

这使得彼得可以通知他的监听者,然后立即返回工作,让进程的线程池来调用这些代理。随着时间的过去,彼得发现他丢失了他工作的反馈,他知道听取别人的赞扬和努力工作一样重要,于是他异步激发事件,但是周期性地轮询,取得可用的分数。

异步通知:委托

不幸地,彼得有回到了一开始就想避免的情况中来,比如,老板站在背后盯着他工作。于是,他决定使用自己的委托作为他调用的异步委托完成的通知,让他自己立即回到工作,但是仍可以在别人给他的工作打分后得到通知:

宇宙中的幸福

彼得、他的老板和宇宙最终都满足了。彼得的老板和宇宙可以收到他们感兴趣的事件通知,减少了实现的负担和非必需的往返“差旅费”。彼得可以通知他们,而不管他们要花多长时间来从目的方法中返回,同时又可以异步地得到他的结果。彼得知道,这并不*十分*简单,因为当他异步激发事件时,方法要在另外一个线程中执行,彼得的目的方法完成的通知也是一样的道理。但是,迈克和彼得是好朋友,他很熟悉线程的事情,可以在这个领域提供指导。

他们永远幸福地生活下去……<完>

深入sql server中的事务

. 概述... 1
. 并发访问不利影响... 1
1. 脏读(dirty read... 1
2. 不可重复读(nonrepeatable read... 1
3. 幻读(phantom read... 1
. 并发访问控制机制... 2
1. ... 2
2. 行版本控制... 2
. 隔离级别... 2
. 事务... 3
1. 事务的模式... 3
1.1. 显式事务Explicit Transactions... 3
1.2. 自动提交事务Autocommit Transactions... 4
1.3. 隐式事务Implicit Transactions... 4
2. 事务的编程... 5
2.1. Transact-SQL脚本... 5
2.2. ADO.NET应用程序接口... 5

一. 概述

当多个用户同时访问数据库的同一资源时,叫做并发访问。如果并发的访问中有用户对数据进行修改,很可能就会对其他访问同一资源的用户产生不利的影响。可能产生的并发不利影响有以下几类:脏读、不可重复读和幻读。
为了避免并发访问产生的不利影响,sql server设计有两种并发访问的控制机制:锁、行版本控制。

二. 并发访问的不利影响

并发访问,如果没有并发访问控制机制,可能产生的不利影响有以下几种

1. 脏读(dirty read

如果一个用户在更新一条记录,这时第二个用户来读取这条更新了的记录,但是第一个用户在更新了记录后又反悔了,不修改了,回滚了刚才的 更新。这样,导致了第二个用户实际上读取到了一条根本就没有存在过的修改后的记录。如果第一个用户在修改记录期间,把所修改的记录锁住,在修改完成前别的 用户读取不到记录,就能避免这种情况。

2. 不可重复读(nonrepeatable read

第一个用户在一次事务中读取同一记录两次,第一次读取一条记录后,又有第二个用户来访问这条记录,并修改了这条记录,第一个用户第二次 读取这条记录时,得到的是跟第一次不同的数据了。如果第一个用户在两次读取之间锁住要读取的记录,别的用户不能去修改相应的记录就能避免这种情况。

3. 幻读(phantom read

第一个用户在一次事务中两次读取同样满足条件的一批记录,第一次读取一批记录后,又有第二个用户来访问这个表,并在这个表中插入或者删 除了一些记录,第一个用户第二次以同样条件读取这批记录时,可能得到的结果有些记录是在第一次读取时有,第二次的结果中没有了,或者是第二次读取的结果中 有的记录在第一次读取的结果中没有的。如果第一个用户在两次读取之间锁住要读取的记录,别的用户不能去修改相应的记录,也不能增删记录,就能避免这种情 况。

三. 并发访问的控制机制

Sql server中提供了两种并发控制的机制以避免在并发访问时可能产生的不利影响。这两种机制是:

1.

每个事务对所依赖的资源(如行、页或表)请求不同类型的锁。锁可以阻止其他事务以某种可能会导致事务请求锁出错的方式修改资源。当事务不再依赖锁定的资源时,它将释放锁。
根据需要锁定资源的粒度和层次,锁有许多类型,主要的有几种:
表类型:锁定整个表
行类型:锁定某个行
文件类型:锁定某个数据库文件
数据库类型:锁定整个数据库
页类型:锁定8K为单位的数据库页
锁的粒度越小,锁定的范围越小,对别的访问的阻塞就越小,但是所用的锁可能会比较多,锁的消耗就比较大。锁的粒度越大,对别的访问的阻塞可能性就越大,但是所用的锁就会比较少,锁的消耗就比较小。
对于编程人员来说,不用手工去设置控制锁,sql server通过设置事务的隔离级别自动管理锁的设置和控制。
Sql server专门管理锁的是锁管理器,锁管理器通过查询分析器分析待执行的sql语句,来判断语句将会访问哪些资源,进行什么操作,然后结合设定的隔离级别自动分配管理需要用到的锁。

2. 行版本控制

当启用了基于行版本控制的隔离级别时,数据库引擎 将维护修改的每一行的版本。应用程序可以指定事务使用行版本查看事务或查询开始时存在的数据,而不是使用锁保护所有读取。通过使用行版本控制,读取操作阻止其他事务的可能性将大大降低。

四. 隔离级别

上面提到了,sql server通过设置隔离级别来控制锁的使用,从而实现并发法访问控制。
Microsoft SQL Server 数据库引擎支持所有这些隔离级别:
l 未提交读(隔离事务的最低级别,只能保证不读取物理上损坏的数据)
l 已提交读(数据库引擎的默认级别)
l 可重复读
l 可序列化(隔离事务的最高级别,事务之间完全隔离)
这几种隔离级别,对应上面三种并发访问可能产生的不利影响,分别有不同的效果,见下表:

隔离级别

脏读

不可重复读

幻读

未提交读

已提交读

可重复读

快照

可序列化

五. 事务

事务是一个逻辑上的单个的工作单元,其中可以包括许多操作,但是它们在逻辑上是一个整体,要么全部完成,要么全部失败,就好像什么操作都没进行似的。
事务是十分可靠坚固的机制,它能保证事务要么全部完成,要么能全部回滚。
l 锁:使用锁的机制尽可能的保证并发事务的隔离性,避免并发的不利影响。
l 事务日志:事务日志记录着整个事务的所有操作步骤,必要的时候靠日志重新开始事务或者回滚事务。不管出现什么状况,哪怕是网络中断,机器断电,甚至是数据库引擎本身出问题了,通过事务日志都能保证事务的完整性。
l 事务管理:保证一个事务的原子性和数据的一致性。一个事务开始后,它要么成功的完成,要么失败,回滚到事务没开始前的那个状态,事务开始做的所有修改都将复原。

1. 事务的模式

控制事务的开始结束的时间点和事务的范围,有几种事务模式:

1.1.显式事务(Explicit Transactions

显式事务通过sql脚本的BEGIN TRANSACTION或者编程接口(API)的开始事务语句启动事务,以sql脚本的COMMIT ROLLBACK语句提交或回滚事务,编程接口(API)的提交事务或回滚事务语句结束事务。都是通过显式的命令控制事务的开始和结束。
从事务开始到事务提交或者回滚是一个完整的事务周期,事务一旦开始,结果要么是提交,要么是回滚。
如果事务范围内发生错误,错误分为几种类型,不同类型的错误有不同的行为。
l 严重错误
比如,客户端到服务端的网络中断了,或者客户的机器被关机了,数据引擎会被通知数据连接已中断,这样严重的错误数据引擎会自动在服务端回滚整个事务。
l 运行时错误
语句之间的“GO”命令形成的区域为命令批次。数据引擎编译和执行语句是以批次为单位的。一次编译一个批次的命令,编译完成后执行这个批次的命令。存储过程是整个被一次编译的,所以一个存储过程内不分批次,整个过程就是一个批次。
大多数情况下,在一个批次中一条语句发生运行时错误,这个语句将被中止,同时同一批次的所有后续语句也不再执行,但同一批次前面已经执行的命令依然有效。但是可以使用了try…catch捕获错误,并进行相应处理,比如执行事务回滚命令。
有一些运行时错误,比如插入了一个主键重复的记录,只中止当前出错的这条语句,后续的语句照样继续执行。这类错误也能被try…catch捕获到。
为了保证整个事务中,任何语句出现错误都回滚整个事务,最简单的方法是在事务开始前设置SET XACT_ABORT ON,这个设置指示数据引擎,在一个事务中遇到一个错误后,不再执行后续的事务,并回滚整个事务。
l 编译错误
遇到编译错误时,错误语句所在的批次不被执行,并不会受SET XACT_ABORT设置的影响。

1.2.自动提交事务(Autocommit Transactions

这个模式是数据引擎的缺省模式,也是各种编程接口的事务缺省模式。每个单独的语句在完成后被提交,失败后被回滚,编程人员不需要指定任何命令。
每个单独的语句就是一个事务的单位,成功了就提交,这句语句执行错误就回滚这条语句,对其他语句的执行不产生影响。注意这里说的执行错误是运行时错误,如果语句本身有编译错误,比如sql语句的关键词拼写错误了,那么发生编译错误语句所在的那个批次的语句都将不被执行。比如:

USE AdventureWorks;
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3));
GO
INSERT INTO TestBatch VALUES (1, 'aaa');
INSERT INTO TestBatch VALUES (2, 'bbb');
INSERT INTO TestBatch VALUSE (3, 'ccc'); -- Syntax error.
GO
SELECT * FROM TestBatch; -- Returns no rows.
GO

上面这段sql中的第三个insert语句values关键字拼写错误,将导致编译错误,结果是跟这个语句在同一批次的所有三条insert语句都将不被执行。
如果上面第三个insert语句是这样的:
INSERT INTO TestBatch VALUES (1, 'ccc'); -- Duplicate key error.
这将产生一个运行时错误“重复的主键”,这条语句将被回滚,但是不影响前面两条insert语句。从这点可以看出,自动提交模式是每条单独的语句要么完成要么回滚,不影响其他语句的执行。

1.3.隐式事务(Implicit Transactions

SET IMPLICIT_TRANSACTIONS ON命令之后的第一条语句开始,就开始一个新的事务,直到遇到COMMIT ROLLBACK语句结束这个事务,下一个语句又是一个新的事务,同样直到遇到COMMIT ROLLBACK语句结束这个事务。这样形成了一个事务链,直到SET IMPLICIT_TRANSACTIONS OFF结束隐式事务,回到默认的自动提交事务模式。
事务中的行为跟显式事务模式是一致的。
事务体现在connection的水平,一个connection具有事务模式,自动提交模式是connection的缺省事务模式,直到BEGIN TRANSACTION语句开始显式事务模式,或者隐式事务被SET IMPLICIT_TRANSACTIONS ON设置,连接的事务模式被置为显式或隐式事务模式,当显示事务被提交或者回滚,隐式事务被置为关闭后,这个连接的事务模式又被置为自动提交模式。

2. 事务的编程

数据库的编程有两种方式,一种应用程序接口(API),包括ODBCADO ado.net等等编程接口,一种是Transact-SQL脚本,典型的是存储过程。

2.1.Transact-SQL脚本

BEGIN TRANSACTION
标记显式连接事务的起始点。
COMMIT TRANSACTION COMMIT WORK
如果没有遇到错误,可使用该语句成功地结束事务。该事务中的所有数据修改在数据库中都将永久有效。事务占用的资源将被释放。
ROLLBACK TRANSACTION ROLLBACK WORK
用来回滚遇到错误的事务。该事务修改的所有数据都返回到事务开始时的状态。事务占用的资源将被释放。

2.2.ADO.NET应用程序接口

SqlConnection 对象使用 BeginTransaction 方法可以启动一个显式事务。若要结束事务,可以对 SqlTransaction 对象调用 Commit() Rollback() 方法。
下面主要以在存储过程中使用事务的编程详加说明
使用事务的目的是保持一段sql语句执行的完整性,要么全部执行成功,只要有一条语句失败就能完全回滚,回到事务开始前的状态。
事务有起点,即通过BEGIN TRANSACTION启动一个事务,其后执行事务中的各个语句,最后要判断,全部语句执行都成功了,就用COMMIT TRANSACTION提交事务,把事务中执行的语句的结果固定下来;如果事务中有任何错误,要能捕获到错误,并执行ROLLBACK TRANSACTION回滚整个事务。
下面是一段示例代码:

USE AdventureWorks;
BEGIN TRANSACTION;
BEGIN TRY
-- 产生一个违反约束的错误.
DELETE FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() as ErrorState,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_LINE() as ErrorLine,
ERROR_MESSAGE() as ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;

把事务中要执行的语句都放在TRY语句块中,保证所有语句产生错误都能被捕获到。如果事务中的语句一旦产生错误,事务中的后续语句不再被执行,直接跳到CATCH语句块执行,进行出错后的后续处理过程。
CATCH语句块中的最主要的工作就是执行事务回滚语句,以回滚整个事务。也可以进行一些其他辅助性的工作,显示错误,记录错误等等。
如果事务中所有语句都没有出错,顺利执行完成,程序就跳过CATCH语句块,执行最后的COMMIT TRANSACTION提交事务。
经常看到有些人使用@@error来捕获错误,判断是否需要回滚事务,代码大概如下:

BEGIN TRANSACTION;
Select xxx from yyyy; --事务中的sql语句
……
If @@error > 0
ROLLBACK TRANSACTION;
Else
COMMIT TRANSACTION;

这里使用@@error来判断事务中所有的语句是否发生错误,并以此来决定是回滚事务,还是提交事务。实际上这么做是是十分错误的。
第一,@@error是针对每个sql语句执行结果,反映的是当前执行的语句出错状态,当执行到下一句,@@error又被重置以反应下一句语句的执行结果。所以用@@error来判断所有语句是否出错是不行的。
第二,sql语句的运行时错误有两类,一类是语句发生了错误,此语句被中止,但后续语句还能被继续执行,一类是语句发生错误后,一个命令批次中的后续的所有语句也不再被执行。当事务中的语句发生这种错误,那么放在最后的If @@error > 0判断语句都不会有机会被执行了。

这样的做法可能导致很严重的后果:如果事务中有语句产生第一类的错误,后续语句都不被执行,原来设计的ROLLBACK TRANSACTION或COMMIT TRANSACTION都没有机会被执行,就是说被这个事务锁了的资源都将得不到释放,产生的后果是,如果这个事务对某些记录设置了共享锁,那这些记录再 也不能被修改,更惨的是如果这个事务对某些记录设置了排他锁,那么读取这些记录的语句一直会被堵塞,执行不下去了。程序也就死在那里了。
所以,在事务中用来捕获语句错误还是需要使用try…catch语句块。

.NET Making Gains Against Java, Survey Says

by Stephen Swoyer
30 September 2008
Who's ahead: Microsoft Corp.'s .NET or Sun Microsystems Inc.'s Java Platform Enterprise Edition (Java EE)?
Five years in and counting, the battle still rages with no clear victor. However, according to a new survey, .NET appears to be widening its lead over Java EE, as the latest revision of the erstwhile Java 2 Enterprise Edition (J2EE) specification is now called. Given the volatility of the .NET/Java EE match-up, that could easily change.
Last year, for example, a survey from development consultancy Evans Data Corp. identified a clear trend in favor of Java development, even though .NET still retained a narrow lead. Thirty-one percent of developers said they planned to tap .NET as their platform of choice for SOA development; 28 percent cited Java.
Evans Data flagged a steep decline in the percentage of developers who expressed a preference for using .NET as a platform for their SOA activities, citing a 20 percent drop in just a six-month period.
This year, the reverse seems to be the case.
According to a new survey from Evans Data, .NET is once again outpacing Java. The survey, which polled 350 developers at enterprise shops with 1,000 or more employees, found that three-fifths (60 percent) of respondents indicated that their .NET investments were growing; fully half said they planned to add additional .NET development personnel.
"These survey results confirm that .NET applications are pervasive in large enterprises and their acceptance and dependability is continuing to increase," said Mike Allen, director of product management for CA Wily Technology, in a statement. CA Inc. -- which markets application performance management (APM) tooling (and which claims that the Evans Data results underscore the importance of effective APM programs) -- is a sponsor of the survey.
There might be something to CA's claims. What's surprising is how much enterprise IT organizations are spending on their next-gen application architecture investments -- particularly for .NET products. More than half of respondents said they're spending about a quarter of their IT application budgets on .NET development or support, while a staggering one-fifth of respondents say they're spending between 75 and 100 percent this way.
Also surprising is the non-partisan heterogeneity of today's enterprise application architectures. Many shops are supporting mixed .NET and Java EE deployments, Evans Data said. A clear majority of respondents said their organizations maintain both .NET and Java groups, for example.
It's a sign of the times, according to industry veteran Jasmine Noel, a principal with consultancy Ptak, Noel & Associates.
"An increasing number of enterprises are realizing the benefits of deploying applications built on both .NET and Java. However, with those benefits come the challenges of managing a heterogeneous environment coupled with the unique issues of both development architectures," Noel said in a prepared statement.
Elsewhere, .NET developers are far more likely than Java coders to blame changes -- at both the application level and in the back-end -- for slowdowns. Java users, on the other hand, disproportionately cite memory leaks and out-of-memory conditions as triggers for application failure.
.NET users were also more likely to cite issues with connectivity to back-end transaction systems, including mainframe systems. Java users, conversely, seem to generate or encounter more bugs. They're also more likely to find fault with JVM or architecture issues than are .NET users (with the .NET CLR, that is).
You can contact the editors about .NET Making Gains Against Java, Survey Says at [email protected].