System.Transactions类

wxwinter 2006-09-01 11:04:31
以后再也不写COM+了,用System.Transactions,发帖留念
========================================================================================

用 using 语句定义了一段隐性事务。如果在该语句块中加入一段对 SQL Server 操作的代码,那么它们将会自动加入这个事务。

void wxd()
{
//开始主事物区
using (System.Transactions.TransactionScope obj_t = new System.Transactions.TransactionScope())
{

System.Data.SqlClient.SqlConnection c = new System.Data.SqlClient.SqlConnection(@"Data Source=WXWINTER\sqlexpress;Initial Catalog=wwxxdd;Integrated Security=True");

System.Data.SqlClient.SqlCommand s = new System.Data.SqlClient.SqlCommand();
s.Connection = c;
s.CommandType = System.Data.CommandType.Text;
c.Open();

//1.事务中查询类
s.CommandText = string.Format("select * from wxd.table_1 ");
s.ExecuteNonQuery(); //执行查询
//此时可对该表进行Select作,无法对表U被锁
MessageBox.Show("停一下,试一试,在数据库里可以Select,无法Insert,Update");


//2.事务中插入类
s.CommandText =string.Format ( "insert into wxd.table_1 (a,b) values ('{0}','8')",DateTime.Now.ToString());
s.ExecuteNonQuery(); //插入记录
//此时无法对该表进行Select 等操作,表已被锁
MessageBox.Show("停一下,试一试,在数据库里无法Select,Insert,Update");


//3.事务中修改类
s.CommandText = string.Format("update top (2) wxd.table_1 set b='{0}'", DateTime.Now.ToString());
s.ExecuteNonQuery(); //修改记录
//此时无法对该表进行Select 等操作,表已被锁
MessageBox.Show("停一下,试一试,在数据库里无法Select,Insert,Update");

////////////////////////////////////////////////////////////////
//在执行开始后,没提交,或取消事物前,
//除[1.事务中查询类]与其并行的Select操作外, 所有对表的操作将等待

int state;
state = 0;
if (state == 0)
{
obj_t.Complete(); //提交
}
else
{
obj_t.Dispose(); //取消
}
//说明:如果不提交出了事物区后,自动回滚
}

}
...全文
742 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
wxwinter 2006-09-05
  • 打赏
  • 举报
回复
对"统一的接口"再补充一下,

虽然我们自已实现事物处理在有些时候可能比用System.Transactions类更灵活,

但基于System.Transactions类来自定义事务,可以将所有的自定义事务都放到同一个事物池中

还可以实现自定义事物与某些支持事物的服务器(如Sql Server,BizTalk)协同

///////////////////////////////////////////
完全自定义的事物好像C的指针........

基于System.Transactions类的自定义事务好像NET的GC...........

个人感觉的一种比喻.....与技术方向无关(^_^)
wxwinter 2006-09-05
  • 打赏
  • 举报
回复
不写了,把以前的贴考走,晚上就结

看到有位老大写了个系例的技术心得,也东施笑颦,写了些

没想到每次最多只能发三贴,多亏各位老大看我可怜,帮兄弟UP一下,让我能接着写

这里的人总是想着接分、升级,没有一个真心想交流技术。

在真实世界中争名逐利还不够,又到这里争,搞什么等级制度

祝:大版主,仙福永享,寿与天齐,千秋万载,一统江湖,号令武林,莫敢不从

祝:北京百联美达美数码科技有限公司,生意兴隆,财源广进

祝:各位老大心想事成

祝:中国的程序员早日升星(是这么说吧)

男儿膝下有黄金,很多问题很容易,何必跪求,到MSDN里搜索一下,都在里放着
active99 2006-09-05
  • 打赏
  • 举报
回复
....关注ing...
wxwinter 2006-09-05
  • 打赏
  • 举报
回复
.................接上上贴............

二阶段提交,事务回滚,事务回调(事件),事务挂起,补偿资源,锁定资源,事务回溯,

概念,高手们都解释过N多遍了,

本人没什么文化,理解有限,

就不说此似是而非的原理,意义,性质,历史,将来,希望,展望,局限,

兄弟没什么文化,也没上过大学(真的),只能用实际应用来举例


1.二阶段提交:
什么意思,就是 "我准备好了吗,你准备好了,是的我也准备好了,提交"

什么是"准备":上例中剪切文件的例子中"将源目录复制到TEMP,将源目录删除"就是准备
什么是"提交": 上例将"TEMP改名就是提交"

准备好了也不见得能提交成功,这也是我前面所说的 “过程操作,瞬间操作”的粒度化分问题

原则上不要在Transactions.IEnlistmentNotification.Commit写里过程操作,

所以前面Transactions解决对象多次被改变后回滚的的例子意义不过是一个演示Transactions工作过程的例子而以

2.回滚,很多解释只是一个恢复原状就过去了。

如何恢复原状,是步骤倒做,状态至回,资源备份,他们不说,咱们一会在后面说

3.事务回调,很多时候子事务的执行要很长一段时间,或者要由其进程或主机完成,这时使用串行可以效率会很低,可以考虑并行,这时就有两个要解决的问题,一是出现错误的子事务通知主事务,二是提到子事物错误通知的主事物通知其他正在执行的子事物。
有点像多线程,其实就是多线程与多进程的操作

4.事务挂起,暂停一个事物,等需要时再接着跑,工作流中常用

是实现补偿资源,事务回溯的前提。

听起来很简单,实现很难,为何这样说,看一下相对论就理解了


5.补偿资源,(^_^)

事物真的是原子性,持久性的吗,

不见得,连原子都不原子了,宇宙都不持久性了,何况事务...............

具体的后面现说,

先举个例子

想到了一个本书上的一个事务的例子(远古人换贝壳),不说了,要真是这样,我想我们现在还是猴子

例子!

一个人在饭店定了20个菜,要请20个朋友

饭店起火了,事物回滚

主人死了,事物回滚

20个朋友都死了,事物回滚

要是有一个朋友有病不能来,或者饭店有一个菜无法做,事物也回滚吗.

补偿一下,事物提交就得了

难道我现在写错了一句,还得把所有贴都删了重写,登一个更证说明不就完了吗


6.锁定资源,高手们举了很多不锁资源的后果,不重复了,

加锁注册,解锁通告,更新通知,死锁这些简单的东西,高手们不屑谈,

我没文化,1+1 这么简单的问题也想显显,咱们后面谈,具体谈,大谈特谈


7.事务回溯
你家是A
你女朋友家是X

你到你女朋友家有

(1)A-B-C-D-E-X

(2)A-B-C-1-2-X

(3)A-B-1-2-3-X

(4)A-1-2-4-5-X

这四条路可以走
当你走第一条路时,E处坏了,不能通过,你是事物回滚,回家

还是退到C处走第(2)条路,还是退到B处走第(3)路

这里我们不谈数据结构,不谈最优算法,不谈链表,二叉树,图

我们要谈回退重试过程中各点的资源管理问题

////////////////////////////////////////////////////////////

----------以上数贴,将事物的来历,目的,意义,应用场景都调侃了一遍

----------对System.Transactions类 的应用场景也有了一个简单交代,

----------下贴正式谈代码实现
bobomouse 2006-09-04
  • 打赏
  • 举报
回复
学习……
jijl2001 2006-09-04
  • 打赏
  • 举报
回复
这个东西也不是想像中的那么好,
wxwinter 2006-09-04
  • 打赏
  • 举报
回复
-----------------------说明-------------------------
1.上面有不少打错的的字

2.发现VS 2005 有个问题,就是把代码粘到Word 2003中时会有如下情况
a1=a2
变成
a=a
------------
Console.WriteLine("监视点1:初始的[对象值]为:" + wxd.对象值.ToString());
变成
Console.WriteLine("监视点:初始的[对象值]为:" + wxd.对象值.ToString());
-------------
也就是后面的数字没了,不知各位是否有这个问题
所以上面有些代码是在Word里改的,可能有部份错误


3.有些代码是直接在Word中打的,没在VS中打,可能会有单词错误,

4.有时用VB.NET有时用C#,有时直接用语言描绘了,以后会全用C#写,

fds2003 2006-09-04
  • 打赏
  • 举报
回复
帮你顶!!
wxwinter 2006-09-04
  • 打赏
  • 举报
回复
接上...........

/////////////////////////////////////////////////////////

因为是想到什么就写什么,有点乱,以后有时间再整理一下吧

////////////////////////////////////////////////////////

还记得上面提过的Access吗,看我如何实现Access事物操作

(办法很多,举一变态的,当轻松一下了)

以下代码不用VB.NET了,也不有C#,用人类语言

!@#$%%^&*()*^&%$ 人类语言的注释 %#%*&*$^&%^$$$%&^

将Access数据库文件复制到一Temp目录

对Access数据进行一系统列的数据操作

从这里开发监视执行性况(Try)

添加,再添加

删除,又删除

修改,还修改

如果以上操作有不成功的(Catch)
将复制到TEMP目录的数据库复制回原目录,覆盖原Access数据库文件

!@#$%%^&*()*^&%$ 人类语言的注释 %#%*&*$^&%^$$$%&^

OK,聪明的大脑相出了绝妙的解决方案............

现在我们用上面的方案与SQL Server一起完成一个协作事物

''''''''''''''''Sql Server操作直接用上例'''''''''''

''''''''''''''''对Access的操作代码放该放到那里'''''''''''

Try

SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand1.ExecuteNonQuery()

SQL事务.Commit()
Catch ex As Exception

SQL事务.Rollback("okok")

End Try
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
这样写吗?

''''''''''''''''''''''''''''''''''''''''''''

Try

SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand1.ExecuteNonQuery()

-------------------------------------------------
try
将Access数据库文件复制到一Temp目录

对Access数据进行一系统列的数据操作

从这里开发监视执行性况(Try)

添加,再添加

删除,又删除

修改,还修改

如果以上操作有不成功的(Catch)
将复制到TEMP目录的数据库复制回原目录,覆盖原Access数据库文件
SQL事务.Commit()
Catch
SQL事务.Commit()
---------------------------------------------------

SQL事务.Commit()
Catch ex As Exception

SQL事务.Rollback("okok")

End Try
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Ok 没问题,有点乱,但实现了,可以将-------------间的代码提出来,写成一个方法或一个类


但现在有一个问题,上面的操作,我想换一下顺序该怎么办

也就是说先执行操作Access,再操作 Sql Server,操作Access时成成,操作Sql Server时出错了,该如

何,
好像也可以解决,再添加一个对复恢Access的回调。

但要还有更多的自定义事务怎么办,而且这些事务又不是一个人开发的怎么办

当然,所有学过面向对象编程的人都会说"定义统一的接口,在同一逻辑关系中处理"

OK,看一下上贴的最后一句话:

"统一的接口,多对象事物协作的前提"

..............下贴..........

准备写

.........(本文正题:)................

二阶段提交

事务回滚

事务回调(事件)

事务挂起

事务回溯

补偿资源

锁定资源
wxwinter 2006-09-04
  • 打赏
  • 举报
回复
现在,事情好像都已经有解决方案了

在数据层(我先这么描术),可以在数据库的存储过程中用使用事务
在中间层(或者叫逻辑层,我先这么描术),可以用DTS,MTS,COM+
在前台(或都叫表示层,我先这么描术),可以用ADO.NET的事物机制

当然,ADO.NET也可以写中间层,COM+也可放到前台,存储过程中也能用ADO.NET,COM+

可是不管如何,事情好像都已经有解决方案了,要System.Transactions出来干吗

因为有的数据库不支持事务............

因为写代码不只是为了操作数据库...............

相信大家都有类似这样的经历:

将一个大目录(有N多子目录与文件)剪切到另一个磁盘上(可能要60分钟以上),

如果这时当机了.....................

如果System.IO类支持事务,以上问题就不用考虑了


其实没有支持事务的IO也不要紧,我们可以自已实现

第一种方式:

1.先将这个大目录复制的要剪切到的磁盘的同级目录,名为temp

2.复制完成后,删除原目录。

3.将temp目录改名为原目录名

这里有两类操作,复制与删除叫过程操作,改名叫瞬间操作。

过程操作,我们认为有明显的阶段性,有发生中断的可有,对资有很大的依赖性
瞬间操作,我们认为无法操制其过程,发生中断的可能性很小,可以认为其不可能在操作进行中出现阶段

性错误。

当然,以是中相对的,操作系统的瞬间操作,对CPU来说可能是一个过程操作,

我们不能把代码的逻辑错误,服务器的电源故障冗余方案,与CPU的过热保护放到一段代码中去实现

也就是说事物处理是靠非事务性代码用逻辑关系实现的,事物也有可能无法回滚事最初状态,

面对这种情况,我们要做的就是合理的划分操作单元,完善逻辑关系(具体后面再细谈)

第二种方式:

对原目录的文件结构建立一个清单,每复制一个文件,就在清单中标记一下,复制完成后再从原目录中删除文件。

好了,不管代码效率如何,总算有了自已IO事物的解决方案,

那我们还要System.Transactions类干吗........

..........见下贴.................

统一的接口,多事物协作的前提
wxwinter 2006-09-04
  • 打赏
  • 举报
回复
接着写.....

在http://community.csdn.net/Expert/topic/4995/4995184.xml?temp=.5229456里发泻了一下
心情好多了

///
ASP.NET的事物处理出现了.....................
///
写错了,应是ADO.NET的事物处理

ADO.NET操作数据库时支持事务,严格的说应是ADO.NET在连接支持事务的数据库时,支持事务

ADO.NET 在连接Access时不"直接"支持事物,因为ADO.NET操作Access时,不能像操作SQL Server那样直接

使用数据库的事务引擎
ADO.NET不是第一个可以在数据库以外使用事物的

以前有DTS,MTS,还有上面说的COM+都可以在数据库以外支持事物

数据库以外支持事物,我想描绘的就是对数据库的事物操作不放在存储过程里,而是在程序代码中实现,

先来个ADO.NET的例子

'''''''''''''''''''''我还用VB.NET写(^_^)'''''''''''''''''''''''''

Dim 事务 As SqlTransaction '定义变量a为事务型

SqlConnection1.Open() 'SqlConnection1对象打开连接

事务 = SqlConnection1.BeginTransaction("okok")
' '用SqlConnection1对象的BeginTransaction方法初始化[事务],
' '参数okok为事务的名()

SqlCommand1.Transaction = 事务

Try '定义一个错误处理,监视两条SQL语句的执行情况

'指定SqlCommand对象要执行的SQL语句,并执行
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand1.ExecuteNonQuery()
'------------------------------------------------

'再次指定SqlCommand对象要执行的SQL语句,并执行
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 2)"
SqlCommand1.ExecuteNonQuery()
'------------------------------------------------

事务.Commit() '提交事物,既两次的SQL语句

Catch ex As Exception '如果两次的SQL语句有一个执行错误

事务.Rollback("okok") '回滚事物,参数okok为要回滚的事物名.

End Try

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

以上实现了对数据库操作的代码层事务处理,

作用与下面的方式相似
''''''''''''''''数据库中'''''''''''''''''
存储过程名
事务
DELETE FROM a WHERE (a = 1)
DELETE FROM a WHERE (a = 2)
结束事务

''''''''''''''''代码中''''''''''''''''''''''
SqlCommand1.CommandText = "存储过程名"
SqlCommand1.ExecuteNonQuery()
'''''''''''''''''''''''''''''''''''''''''
那为何要写到程序中,

其实对于上例,我强列建议写在数据库的存储过程中,而不在代码中实现

可是如果要协同操作的数据库是两个以下,比如一个是Access,一个是Sqlserver,一个是oracle,要将在这

三个数据库中的三条记录的修改放到同一个事物中完成,该如何

当然,在SQL Server的存储过程中也可以实现,

但这种操作,本人觉得还是写一个后台代码操作的中间层好一些

看一下例子
(上例中三类数据库事物协同,有点复杂,特别是还有一个内核不支持事务的Access,这个的解决下面会

提到, 这里先用三个SQL Server来举例)





三个SQL Server 当然要三个连接了

SqlConnection1
SqlConnection2
SqlConnection3

还得有三个各自独立的事务

SqlTransaction_事物1
SqlTransaction_事物2
SqlTransaction_事物3

然后分别绑定

SqlTransaction_事物1 = SqlConnection1.BeginTransaction("事物1")
SqlTransaction_事物2 = SqlConnection1.BeginTransaction("事物2")
SqlTransaction_事物3 = SqlConnection1.BeginTransaction("事物3")


还得有三个执行SQL语句的SqlCommand


SqlCommand1.Transaction = SqlTransaction_事物1
SqlCommand2.Transaction = SqlTransaction_事物2
SqlCommand3.Transaction = SqlTransaction_事物3


接下来写代码,错误扑获用并行嵌套都可,具体问题具体分析


Try
'对第1个数据库操作
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand1.ExecuteNonQuery()
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 2)"
SqlCommand1.ExecuteNonQuery()

'对第2个数据库操作
SqlCommand2.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand2.ExecuteNonQuery()
SqlCommand2.CommandText = "DELETE FROM a WHERE (a = 2)"
SqlCommand2.ExecuteNonQuery()

'对第3个数据库操作
SqlCommand3.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand3.ExecuteNonQuery()
SqlCommand3.CommandText = "DELETE FROM a WHERE (a = 2)"
SqlCommand4.ExecuteNonQuery()

SqlTransaction_事物1.Commit()
SqlTransaction_事物2.Commit()
SqlTransaction_事物3.Commit()
Catch ex As Exception

SqlTransaction_事物1.Rollback("事物1")
SqlTransaction_事物2.Rollback("事物2")
SqlTransaction_事物3.Rollback("事物3")

End Try


当然
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 1)"
SqlCommand1.ExecuteNonQuery()
SqlCommand1.CommandText = "DELETE FROM a WHERE (a = 2)"
SqlCommand1.ExecuteNonQuery()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
这种操作,应该写到数据库的存储过程中,以下面这种方法操作

'''''''''''''''''''''''''''''''''''''''''''''''''''''''
Try
'对第1个数据库操作
SqlCommand1.CommandText = "存储过程"
SqlCommand1.ExecuteNonQuery()

'对第2个数据库操作
SqlCommand2.CommandText = "存储过程"
SqlCommand2.ExecuteNonQuery()

'对第3个数据库操作
SqlCommand2.CommandText = "存储过程"
SqlCommand2.ExecuteNonQuery()

SqlTransaction_事物1.Commit()
SqlTransaction_事物2.Commit()
SqlTransaction_事物3.Commit()
Catch ex As Exception

SqlTransaction_事物1.Rollback("事物1")
SqlTransaction_事物2.Rollback("事物2")
SqlTransaction_事物3.Rollback("事物3")

End Try
'''''''''''''''''''''''''''''''''''''''''''''''''''''''

上面只是一个思路,至于保存点,事物嵌套,条件回滚都是ADO.NET的基本操作,这里就不多说了

我们还把话题回到System.Transactions类上

.........下贴...................
ilove8 2006-09-04
  • 打赏
  • 举报
回复
关注,帮你顶
addwing 2006-09-04
  • 打赏
  • 举报
回复
关注,帮你顶!
Dennis_maomao 2006-09-02
  • 打赏
  • 举报
回复
wxwinter 2006-09-02
  • 打赏
  • 举报
回复
为了,在事物用中多次调用赋值方法,然后回滚
如此改动
====================================================
public class 对象_参与事务
{
public int 对象值;

public Guid 事物ID = Guid.NewGuid();


public void 方法_参与事务(int 要赋的值)
{
Console.WriteLine("事务GUID号:" + 事物ID.ToString());


事务处理环节 obj事物处理环节= new 事务处理环节(this, 要赋的值);

Transaction.Current.EnlistDurable(事物ID, obj事物处理环节, EnlistmentOptions.None);

}

}
public class 事务处理环节 : IEnlistmentNotification
{
private 对象_参与事务 obj对象_参与事务; //用于存放构造时传入的[对象_参与事务]对象
private int 旧值; //保存[对象_参与事务.对象值]在事件中赋值前的原值
private int 新值; //保存[对象_参与事务.对象值]在事件中所赋的值


public 事务处理环节(对象_参与事务 obj, int value)
{

obj对象_参与事务= obj;
旧值= obj.对象值;
新值= value;
}



//提交事物
void IEnlistmentNotification.Commit(Enlistment enlistment)

{

obj对象_参与事务.对象值= 新值;
Console.WriteLine("[对象值]为:" + obj对象_参与事务.对象值.ToString() + " | 此时[对象值]已为所赋的值,事物已提交");

enlistment.Done();
Console.WriteLine("自定义事物已提交");

}


//存在无法协调同步的问题
void IEnlistmentNotification.InDoubt(Enlistment enlistment)
{
throw new Exception("自定义事物操作没有被执行.");
}

//准备提交事物
void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment)
{
Console.WriteLine("自定义事物准备中.......");
preparingEnlistment.Prepared();
}

//回滚事物
void IEnlistmentNotification.Rollback(Enlistment enlistment)
{

enlistment.Done();

}
}//自定义事务处理环节
void z()
{
对象_参与事务 wxd = new 对象_参与事务();

wxd.对象值=123; //赋一初始值

Console.WriteLine("监视点1:初始的[对象值]为:" + wxd.对象值.ToString());


//开始主事物区
using (TransactionScope obj_TS = new TransactionScope())
{
Console.WriteLine("监视点2:(事物区最后一行代码)进入事务区");

wxd.方法_参与事务(456); //使用事物方法为[wxd.对象值]赋值

wxd.方法_参与事务(1);

wxd.方法_参与事务(2);

wxd.方法_参与事务(3);

wxd.方法_参与事务(4);

wxd.方法_参与事务(5);

Console.WriteLine("监视点3:事务区代码执行完毕,准备提交或回滚");

//obj_TS.Complete(); //提交事物

Console.WriteLine("监视点4:(事物区最后一行代码)[对象值]为:" + wxd.对象值.ToString());

}//结束事物区



System.Threading.Thread.Sleep(1000);

Console.WriteLine("监视点5:(事物区后第一行代码)[对象值]为:" + wxd.对象值.ToString());

Console.WriteLine("------我是一条线,我应该出现在最后------------");
}
=====================================
结果

监视点1:初始的[对象值]为:123
监视点2:(事物区最后一行代码)进入事务区
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
事务GUID号:6cd13301-c232-4371-903f-1d3a782da322
监视点3:事务区代码执行完毕,准备提交或回滚
监视点4:(事物区最后一行代码)[对象值]为:123
监视点5:(事物区后第一行代码)[对象值]为:123
-------------------我是一条线,我应该出现在最后-----------------------

===========================================
实现了多次操作的回滚

此种方法对赋值类可以,但如果是大数据量的操作,将操作放在提交事物的方法中,会有不妥

=======================================
进一步探讨见下贴

wxwinter 2006-09-02
  • 打赏
  • 举报
回复

需求的变化是无止境的,是人们无法预见的.....

现在要与其他的金融系统对接,而且要使用WebServicr方式,数据库开发人员第一时间推掉了该工作.
理由是对WebService不熟,而且对方也不可能允许他们在对方的数据库中写存储过程什么的.....
还有对方的数据库是在X系统上的Y数据库,与他们现在用的不同....

前台开发人员现在要面对数据操作了,这种数据操作是数据库开发人员所不熟的,
于是他们做了分工,一部分人写前台,一部分人写前台与数据库之间的部分,有人管他叫中间层,写中间层的人就叫后台开发人员

于是现在有了 前台开发人员,中间层开发人员,数据库开发人员.

开发模式也进入了三层开发模式

为了解决跨系统的事物处理,

ASP.NET的事物处理出现了.....................

下贴.....
wxwinter 2006-09-02
  • 打赏
  • 举报
回复
现在问需求升级!

该系统的提供商决定每个月定期收一定的用户管理费,并由系统自动划账
系统划账模块的数据库操作代码使用上面完成的模块就行


该功能的添加与现有模块将产生一个冲突
即用户划账与系统划账在一个千载难逢的时刻,同时运行了..........

(当然上面的代码可以解决这个冲突,这个例子只是把一系例问题分解了)

这种情况有很多意想不到的情况发生,比如用户的钱为负数了,而系统是不许用户透支的....

锁!同一时刻只能由一个事物来控制资源,数据库开发人员想到了解决方案,但实现该方案又使数据库开发人员掉入了焦油潭

数据库开发商在听到了数据库开发人员的抱怨后,终于升级了数据库事物处理机制,为事物处理加上锁,并提供了销的级别
数据库开发商如何实现事物锁,在后面将具体提到,

现在继续数据库开发人员的恶梦.............

收了一次费,用户返映很大,所以决定取消收费,并退还上次所收的费用

数据库开发人员面要写一个模块

update 钱数+100

将收的100元管理费还给用户,

现在又有一个问题,该系统内有1000000000000000000000000000000000000000000个用户,
由于系统使用的是386,处理数度比效慢,这个行为要执行好几天,

如果使用事物,用户在这几天将无法划账,
如果不用事物,中途当机,无法确定那些用户已得到退款,那些还没有...........

数据库开发商即时提供了大数据更新解决方案,在后面将具体提到,

需求永远是变化的,由于系统压力过大,终于又添加了一台主机......

将一部分用户分到另一台主机的数据库中了......

我们前面提到的两个主角,A用户,与B用户也被分到了不同的主机上

A用户与B用户的划账再次让数据库开发人员惆怅.........

数据库开发商又即时提供了分布式事物处现方案,在后面将具体提到.............

数据库开发人员再一次渡过难关..........

可以前台开发人员的难题又来了......................

见下贴......
wxwinter 2006-09-02
  • 打赏
  • 举报
回复
接着写...............

这一贴与技术无关,只谈事物处理的需求演变

看一下如下需求的产生及解决方案

开始事务
1.同一数据库内划账
2.数据库间划账
3.向某用户发信
4.将本地一文件上传到指定服务器
5.将远程主机一目录内容同步到本地目录
6.向连接到本机COM口一电机发出指令,向水池蓄100升水
7.关闭远程一计算机
结束事务

要求,1,2,3,4,5,6,7的操做在同一事物内完成

看一看在解决上述问题时,事物回滚,事物提交,事物准备,事物挂起,事物通知,事物回退,事物回调,事物并行,事物串行,事物资源补偿,资源锁 ,等的问题是如何出现,并如何解决的
///////////////////////////////////////////////////////
先从一个小问题开始..............

假如有这样一个数据库,

/////////////
用户|钱数
a |500
b |600
/////////////

两个用户之间的划账问题,
这里假设不需要或我不会使用交易流水账的方式跟踪交易活动,使用汇总的方式体现钱数的变化。

在这里我且只用update [钱数] 的方式进行用户间的划账.

////////////////////////////////////////
需求1:a用户给b用户划自已支配数额的账

设计如下:
.............................
x1=a要划的账

x2= select 钱数 where a用户

if x2 < x1
update 钱数-x1 where a用户
update 钱数+x1 where b用户
..............................

OK 设计完成! 没有问题! 没有问题..............

但在[update 钱数-x1 where a用户] 后,b用户就消户了,[update 钱数+x1 where b用户]没有执行对象了


代码作如下修改:

.............................
x1=a要划的账

x2= select 钱数 where a用户

if x2 < x1
update 钱数-x1 where a用户
如果 [update 钱数+x1 where b用户] 不成功
update 钱数+x1 where a用户
..............................
OK ,问题解决!
但.....
如果在[update 钱数-x1 where a用户] 后数据库就当掉
如果[update 钱数-x1 where a用户] 就出错
如果[update 钱数+x1 where a用户] 时数据库当掉
........................
接着改代码,这是一个焦油潭....

以上问题由数据库开发商提供解决方案(他的解决方案以后再说)

事物处理(将操作数据的代码放入存储过程,由数据库处理)
.........................................
BEGIN TRANSACTION 事务
Begin
update 钱数-x1 where a用户
update 钱数+x1 where b用户

If @@error=0
Commit Transaction 事务
Else
Rollback Transaction 事务
End
..........................................

OK ,问题解决!,至少前台开发人员问题解决,再有问题找数据库开发人员或数据库提供商

到此先放前台开发人员一马(一会再烦他)

看一下数据库开发人员要面对的一个问题....

见下贴......
foyuan 2006-09-02
  • 打赏
  • 举报
回复
xue xi
ilove8 2006-09-02
  • 打赏
  • 举报
回复
mark
加载更多回复(6)

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧