关于.Net中的数据库事物,好象很不方便,比如我要实现如下的事物操作,怎么做?
.Net中的定义数据库事物
SqlTransaction myTrans ;
myTrans =myCon.BeginTransaction();
cmdPub.Transaction = myTrans; //定义cmdPub在 myTrans中
//在此可以通过cmdPub对数据进行操作
myTrans.Commit();
但是我对数据库的操作都是调用另一个类(模块)中方法或者是调用了一个模块的方法操作数据库的
那么类似上面的cmdPub.Transaction = myTrans; //定义cmdPub在 myTrans中 语句根本没办法定义
而不定义此语句,而BeginTransaction与 Commit中的所有对数据库的操作却受不到事物控制了
而Delphi的ADO中,只要在BeginTransaction与 Commit对数据库的操作,就自动封装为一个事物了
在.Net中,怎么来解决我的问题?
问题点数:20、回复次数:14Top
1 楼ripper(rIPPER)回复于 2002-05-10 17:23:27 得分 3
你可以在不同的对象直接共享你的sqlconnection,这样就解决了
另外一个方法是使用serviced component中的分布式事务,编程很简单,性能不如上面一种方法Top
2 楼wenzm(魔术师)回复于 2002-05-10 17:25:15 得分 0
我觉得这样的编程需求是很常见的,比如我在一个Project中定义了一个Class专门用来 操作数据,如方法
public DataTable GetTable(string sDbConStr,string sGetFieldSQL)
---通过传入连接字符串和查询的SQL语句,返回一个结果集
public bool UpdateData(string sDbConStr,string sSQL)
---通过传入连接字符串和更新的SQL语句,来更新数据
这样的话我就不要在操作数据库中书写大片重复的代码来操作数,而直需一条SQL就可以了
但这样我就碰到了上面的关于事物的操作!
特别,我在一个Form上保存一个结果时需要保存两个表,一个表的保存是在这个Form中完成的,但是另一个表的保存我却是调用放在此Form上的一个自己写的UserControl的Save方法来保存的,怎么把对这两个表的操作封装到一个数据库事物中呢? 急需解决Top
3 楼wenzm(魔术师)回复于 2002-05-10 17:29:23 得分 0
ripper(rIPPER):
你说的serviced component我不知道是各什么东东,但
共享sqlconnection是可以,但cmdPub.Transaction = myTrans还是没办法设置啊除非你让我把cmdPub共享,这样也不好吧!
另外 共享sqlconnection也是不可行的,比如我上面说的在UserControl中的数据库操作 ,Top
4 楼Yang_Wenli(Yang_Wenli)回复于 2002-05-10 21:18:39 得分 1
我觉得你说的问题不存在呀,既然你已经把Connect封装了,你完全可以连事务也封装进你的类
我觉得可以只样
public DataTable GetTable(string sDbConStr,string sGetFieldSQL)
{
//开始事务
//运行
//提交事务
}Top
5 楼wenzm(魔术师)回复于 2002-05-11 09:07:42 得分 0
to Yang_Wenli(Yang_Wenli):
这怎么行呢? 我是要把“多次(个)调用 UpdateData(string sDbConStr,string sSQL),即多次执行UpdateData操作封装在一个事物中)
Top
6 楼wenzm(魔术师)回复于 2002-05-11 09:14:43 得分 0
再说详细一点,举个例子:
我要在一个保存操作中要更新三个不同的Table——执行三次更新语句(Update) 这三个Update对应的更新语句分别为 UpdSQl1,UpdSQl2,UpdSQl3
则我在保存事件中必须 连续三次调用Class的UpdateData方法
Procedure Void Save(sDbConStr)
{
UpdateData(sDbConStr,UpdSQl1);
UpdateData(sDbConStr,UpdSQl2);
UpdateData(sDbConStr,UpdSQl3);
}
请问如何解决!?
不要叫我修改CLass的UpdateData的方法,然后使此方法能一次传入一个SQL语句数组(比如把上面的UpdSQl1,UpdSQl2,UpdSQl3做为一个字符书数组传入)
然后在UpdateData中定义事物,并逐个取出UpdSQl3执行。
Top
7 楼Sunny3141(太阳)回复于 2002-05-11 10:02:46 得分 1
仅供参考:
产生连接CNN
BEGIN
传给模块SAVE(CNN,SAVEDATASTRING,......)
.
.
.
.
END
把UpdateData(string sDbConStr,string sSQL)改为UpdateData(数据连接对象 cnnObject,string sSQL)Top
8 楼wenzm(魔术师)回复于 2002-05-11 12:17:36 得分 0
楼上说的还是不行!
类似cmdPub.Transaction = myTrans; 的语句还是无法“解决”Top
9 楼wenzm(魔术师)回复于 2002-05-11 12:18:29 得分 0
因为cmdPub是在UpdateData内的,而myTrans不可能定义在UpdateData内!Top
10 楼dreammaster(天涯)回复于 2002-05-11 12:41:09 得分 15
我给大家一点思路:
对于非返回提交,我写了一个方法,放在Util类中
public static void Execute(string aSqlStr, SqlTransaction aTrans)
{
if (aTrans.Connection == ConnectionState.Closed)
{
aTrans.Connection.Open();
}
Try
{
SqlCommand cmd = new SqlCommand(aSqlStr, aTrans.Connection, aTrans);
cmd.ExecuteNonQuery();
//这里不要提交事物
}
catch(Exception e)
{
throw e;
//这里不要rollback
}
}
以上是方法
ok,以下是在类中的调用
public void AddItem(Item aItem)
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
SqlTransaction aTrans = conn.BeginTransaction(IsolationLevel.ReadCommited, "AddItem");
try
{
string aSqlStr = "";//要提交的语句
Util.Execute(aSqlStr, aTrans);
aSqlStr= "";//更多现一事物中的sql
Util.Execute(aSqlStr, aTrans);
aTrans.Commit();//提交
}
catch(Exception e)
{
aTrans.RollBack("AddItem");
throw e;
}
finally
{
conn.Close();
}
}
这样可以保证所有该方法内的提交在同事务中,不会出现问题。
以上仅个人之见,请指正,不适用于有参数的SqlCommand, sqlTop
11 楼wenzm(魔术师)回复于 2002-05-13 12:30:33 得分 0
to dreammaster(天涯) :
你测试过你的方法能保证事物性吗?可能你没看我前面的讨论吧, 我开始的想法和你是一样的,也是这样 做的,但根本未能起到事物的作用。
Delphi这样就可以了!
我也想这样Ok
Top
12 楼ripper(rIPPER)回复于 2002-05-13 12:34:26 得分 0
索性用分布式事物算了,省得麻烦Top
13 楼dreammaster(天涯)回复于 2002-05-13 12:47:28 得分 0
to wenzm(疯之驴)
在我的程序中大量采用了这种方法,经实验完全可以控制事务,你的为什么不行呢?是不是中间存在什么差别?Top
14 楼dreammaster(天涯)回复于 2002-05-13 12:53:44 得分 0
wenzm(疯之驴)
我是要把“多次(个)调用 UpdateData(string sDbConStr,string sSQL),即多次执行UpdateData操作封装在一个事物中)
这不简单么
你可以过载
UpdateData(string sDbConStr, string sSQL, SqlTranasaction aTrans)
只要aTrans是统一的,他们就一定在同一个事物内,你的为什么不行,如果你的UpdateData方法调一下提交一下,你又怎么能保证他们多次执行在同事务下,我的方法已经在实际中大量应用,决没有问题.
Top
15 楼wenzm(魔术师)回复于 2002-05-14 11:22:01 得分 0
dreammaster(天涯)方法非常好,可行,我要想达到的就是这个目的! 虽然麻烦一点,但比未能事物总是好。我现在做的一个有关流程的东西,因为设计到太多的表的操作,特别,很多对表的操作又被封装在了不同的类模块中,如果不能事物,其出错几率太大了,如不用事物,根本无法进入实际运行 。
我其实原来做的和你一样,但就是没有想到把Trans作为参数传入到UpdateData中,有的时候,一个人埋头苦想,很容易进入死胡同,技术性的东西,特别是编码方面的,看来还非得多多交流不可,个人总是有自己的思维定是。
收益非浅! 非常感谢!Top




