300分,解答关于COM+分布式事务的问题,有劳大侠! (300分)

  • 主题发起人 主题发起人 Fox2008
  • 开始时间 开始时间
F

Fox2008

Unregistered / Unconfirmed
GUEST, unregistred user!
正在设计COM+的架构,我是根据李维大师推荐的利用协调对象的方式处理的,即有以下模块:
1.连接SQL SERVER数据库的数据模块组件,设为"支持事务",在组件中加入了查询以及更新主从表的代码,部分代码如下:
//查询
function TMtsDataBase.GetTableDesc(const Db, Sql: WideString;
var vDatas: OleVariant): WideString;
begin
try
try
AdcDataBase.DefaultDatabase:=Db;
AdsTableDesc.Connection:=AdcDataBase;
AdsTableDesc.Close;
AdsTableDesc.CommandText:='';
AdsTableDesc.CommandText:=Sql;
AdsTableDesc.Open;
vDatas:=DspTableDesc.Data;
if AdsTableDesc.IsEmpty then
Result:='GET_NOREC'
else
Result:='GET_SUCCESS';
SetComplete;
except
Result:='GET_FAILD';
SetAbort;
end;
finally
AdsTableDesc.Close;
end;

end;
//更新
function TMtsDataBase.UpdateDataBase(const Db: WideString;
var vDatasTableDesc, vDatasFieldDesc: OleVariant): WideString;
var
intErrCount:Integer;
begin
DefaultDb:=Db;
try
if Not VarISNull(vDatasTableDesc) then
begin
vDatasTableDesc:=DspTableDesc.ApplyUpdates(vDatasTableDesc,0,IntErrCount);
if intErrCount > 0 then
begin
result := 'UPDATE_MASTERFAILED';
SysUtils.Abort;
end;
end;

if Not VarISNull(vDatasFieldDesc) then
begin
vDatasFieldDesc:=DspFieldDesc.ApplyUpdates(vDatasFieldDesc,0,IntErrCount);
if intErrCount > 0 then
begin
result := 'UPDATE_DETAILFAILED';
SysUtils.Abort;
end;
end;

Result:='UPDATE_SUCCESS';
SetComplete;
Except
on Exceptiondo
SetAbort;
end;
end;
2,查询协调对象,设为"支持事务",利用接口调用的方式调用组件1的查询方法,代码如下:
function TDataQueryObj.GetTableDescCoor(const strDb, strSql: WideString;
var vaDatas: OleVariant): WideString;
var
MtsDataBaseObj:IMtsDataBase;
begin
try
OleCheck(ObjectContext.CreateInstance(CLASS_MtsDataBase,IID_IMtsDataBase,MtsDataBaseObj));
Result:=MtsDataBaseObj.GetTableDesc(strDb,strSql,vaDatas);
SetComplete;
Except
Result:='GET_FAILD_COOR';
SetAbort;
end;
end;
3,更新协调对象,设为"需要事务"方式,利用接口调用的方式调用组件1的更新方法,代码如下:
function TDataUpdateObj.UpdateDataBaseCoor(const strDb: WideString;
var vDataTableDesc, vDataFieldDesc: OleVariant): WideString;
var
MtsDataBaseObj:IMtsDataBase;
begin
try
OleCheck(ObjectContext.CreateInstance(CLASS_MtsDataBase,IID_IMtsDataBase,MtsDataBaseObj));
Result:=MtsDataBaseObj.UpdateDataBase(strDb,vDataTableDesc,vDataFieldDesc);
if Result='UPDATE_SUCCESS' then
SetComplete
else
SetAbort;

Except
on Exceptiondo
begin
Result:='UPDATE_FAILD_COOR';
SetAbort;
end;
end;
end;
4,前台:前台调用时一切正常,查询,新增保存都可以,事务也有控制,
[blue]
但是删除时有问题,我是这样处理:
在主表的删除触发器中写入删除从表的代码,前台只删除主表,代码如下:
CREATE TRIGGER TableDesc_Del ON [dbo].[t_TableDescription]
FOR DELETE
AS
declare @TableID int
Select @TableID=FTableID From Deleted
--Delete From t_FieldDescription where FTableID=@TableID
if @@error<>0
begin
Rollback Tran
raiserror('出错!',-999,1)
END
[/blue]
[red]
最终问题:
删除,主表执行保存时出现:"没有活动事务"的错误,跟踪事务发现主表执行保存后事务就被中止了,请问如何解决?触发器是不是把事务一起提交了?当在触发器写入其他一些如查询计算的代码时却没有错误,何解?
[/red]
 
各位,怎么没有回答,我在等米下锅呀!
 
给你个建议,别用TRIGGER。
 
好象你的触发器有问题,随手改了一下,不一定对
CREATE TRIGGER TableDesc_Del ON [dbo].[t_TableDescription]
FOR DELETE
AS
begin
tran
Delete From t_FieldDescription where FTableID in (Select FTableID From Deleted)
if @@error<>0
begin
Rollback Tran
raiserror('出错!',-999,1)
END
commit tran
 
迷糊了吗?
他是要主表子表一个 事务迪,所以建议表用触发器拉,一个事务跨2个进程我还真没做过。
 
SysUtils.Abort;是什么?
还要在三层中,最好不要用到触发器
 
不用触发器那不是太难受了!
各位大侠,再出招破解呀!
 
把前台程序都拿出来。不然怎样解决。
 
>>Fox2008:
我正在学,但是客户端调用时,提示"Interface no support". 请问怎么解决??
是不是在客户端也安装COM+组件??
 
TO:胡萝卜
还是你的身份验证有问题,你是不是服务器和客户端中的用户密码都是空的?
 
后台只有一个库
没有必要用MTS事务
 
>>xujh
服务器和客户端的guest用户的密码都是空的.
请问,是不是把COM+组件Export两种,一种安装在服务器端,一种安装在客户端??
 
我现在在服务端和客户端都加了一个用户,但是客户端长时间连接,没有响应,是什么原因??
 
我如何知道服务器端已经运行???
 
帮你改了下,不过不一定对,毕竟对你的程序不是太了解,你先试试看吧,或者说这个方法能不能给你点启示.
CREATE TRIGGER TableDesc_Del ON [dbo].[t_TableDescription]
FOR DELETE
AS
declare @TableID int
Set @TableID=FTableID
if (select count(FTableID) from deleted where FTableID=@TableID)<>(select count(FTableID) from deleted)
begin

raiserror ('出错!',16,1)
rollback tran
end
 
Com+用户的操作系统最低要求是什么??
 
用触发器有什么不好?
 
建议不用触发器,我没认真看你的文章,我有我的处理经验,100%可以,不过是用ADO的,
其实也差不多,你在执行任何的插入,修改,删除操作,都有先启动事务,
如:
try
if not adoconn.InTransaction then
adoconn.begin
Trans;
//
//
adoconn.CommitTrans;
except
on E:exceptiondo
begin
if adoconn.InTransaction then
adoconn.RollbackTrans;
end;
end;
还有处理主从表的操作,一定要先处理子表
 
原来是这样,我看明白了.
COM+的事务不同与SQL Server 的事务
你可以把删除明细数据也放在前台做,放在COM+的事务里面.
但不需要回滚那一句就行了.
 
如果简单地讨论事务控制的话,在COM+下,利用COM+的事务管理就足够了,不需要用到触发器。
最简单的办法,就是做一个提交用的COM+对象和一个协调用的COM+对象。在协调对象的一个提交函数里提交2个表,如果某个表提交不成功就ABORT。而协调对象则在这个提交函数里调用2次提交对象的实际拿来做提交的函数。
这样,提交对象的提交函数被协调对象在一个事务里调用了2次,其中一次不成功则被协调对象的事务回滚了。我自己反复测试过,这样的写法可以控制N个表在一个COM+的事务里提交成功的。只要有一个表不成功就会全部返回。当然,数据库采用的是ADO+SQL SERVER。因为据说只有MS自己的东东才完全支持COM+的事务。其它的数据库我也没试过。
 
后退
顶部