我公司有个软件采用用的三层结构,其中间层采用com+组件实现,改组件的接口如下
Type
IRDMCardServer=interface(IAppServer)
BeginTrans(..);
CommitTrans(..);
RollBackTrans(..);
SelectData(..);
ExcuteData(..);
end;软件客户端大体上是这样写的:
fconnection.AppServer.BeginTrans(..);
try
//一系列的业务操作;
fconnection.AppServer.SelectData(..);
fconnection.AppServer.ExcuteData(..);
...
//提交事务
fconnection.AppServer.CommitTrans(..);except
//异常则回滚
fconnection.AppServer.RollBackTrans(..);
end;实现如下:
type
TRDMCardServer = class(TMtsDataModule, IRDMCardServer)
fconnection: TADOConnection;
fProvider: TDataSetProvider;
fdataset: TADODataSet;
fcmd: TADOCommand;
procedure MtsDataModuleActivate(Sender: TObject);
procedure MtsDataModuleDeactivate(Sender: TObject);
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
procedure BeginTrans(out pResult, pMsg: WideString); safecall;
procedure CommitTrans(out pResult, pMsg: WideString); safecall;
procedure SelectData(const sSQL: WideString; out sPrvName: WideString);
safecall;
procedure ExecuteData(const sSQL: WideString; out pResult,
pMsg: WideString); safecall;
procedure RollBackTrans(var pResult, pMsg: WideString); safecall;
public
{ Public declarations }
end;var
RDMCardServer: TRDMCardServer;implementation{$R *.DFM}class procedure TRDMCardServer.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;procedure TRDMCardServer.BeginTrans(out pResult, pMsg: WideString);
begin
//EnableCommit;
fconnection.BeginTrans;
end;procedure TRDMCardServer.CommitTrans(out pResult, pMsg: WideString);
begin
fconnection.CommitTrans;
//SetComplete;
end;procedure TRDMCardServer.SelectData(const sSQL: WideString;
out sPrvName: WideString);
var
par,tmp:OleVariant;
cnt:integer;
begin
//EnableCommit;
fDataSet.Close;
fDataSet.CommandText:=sSQl;
fDataSet.Open;
sPrvName:=fprovider.Name;
end;procedure TRDMCardServer.ExecuteData(const sSQL: WideString; out pResult,
pMsg: WideString);
var
par,tmp:OleVariant;
cnt:integer;
begin
//EnableCommit;
try
fcmd.CommandText:=sSQL;
fcmd.Execute;
pResult:='1';
except
pResult:='0';
end;
end;procedure TRDMCardServer.RollBackTrans(var pResult, pMsg: WideString);
begin
// SetAbort;
fconnection.RollBackTrans;
end;procedure TRDMCardServer.MtsDataModuleActivate(Sender: TObject);
var
Path: array[0..MAX_PATH] of Char;
Result,strPath: String;
begin
SetString(Result, Path, GetModuleFileName(HInstance, Path, SizeOf(Path)));
strPath:= ExtractFilePath(Result);
if not fConnection.Connected then
begin
fConnection.ConnectionString := 'FILE NAME=' + strPath + '\Local.UDL' ;
fConnection.Connected:=True;
end;
end;procedure TRDMCardServer.MtsDataModuleDeactivate(Sender: TObject);
begin
fConnection.Connected:=False;
end;initialization
TComponentFactory.Create(ComServer, TRDMCardServer,
Class_RDMCardServer, ciMultiInstance, tmBoth);
end.软件中间层只是简单传送了sql语句到数据库服务器,并没有处理业务逻辑,业务逻辑是在客户端通过事务来保证其完整正确性的。
中间层没起到实际作用,但是软件太庞大,不好改太多,我想只要客户端能控制事务也行,可是总是不能回滚。
请高手指点!
Type
IRDMCardServer=interface(IAppServer)
BeginTrans(..);
CommitTrans(..);
RollBackTrans(..);
SelectData(..);
ExcuteData(..);
end;软件客户端大体上是这样写的:
fconnection.AppServer.BeginTrans(..);
try
//一系列的业务操作;
fconnection.AppServer.SelectData(..);
fconnection.AppServer.ExcuteData(..);
...
//提交事务
fconnection.AppServer.CommitTrans(..);except
//异常则回滚
fconnection.AppServer.RollBackTrans(..);
end;实现如下:
type
TRDMCardServer = class(TMtsDataModule, IRDMCardServer)
fconnection: TADOConnection;
fProvider: TDataSetProvider;
fdataset: TADODataSet;
fcmd: TADOCommand;
procedure MtsDataModuleActivate(Sender: TObject);
procedure MtsDataModuleDeactivate(Sender: TObject);
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
procedure BeginTrans(out pResult, pMsg: WideString); safecall;
procedure CommitTrans(out pResult, pMsg: WideString); safecall;
procedure SelectData(const sSQL: WideString; out sPrvName: WideString);
safecall;
procedure ExecuteData(const sSQL: WideString; out pResult,
pMsg: WideString); safecall;
procedure RollBackTrans(var pResult, pMsg: WideString); safecall;
public
{ Public declarations }
end;var
RDMCardServer: TRDMCardServer;implementation{$R *.DFM}class procedure TRDMCardServer.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;procedure TRDMCardServer.BeginTrans(out pResult, pMsg: WideString);
begin
//EnableCommit;
fconnection.BeginTrans;
end;procedure TRDMCardServer.CommitTrans(out pResult, pMsg: WideString);
begin
fconnection.CommitTrans;
//SetComplete;
end;procedure TRDMCardServer.SelectData(const sSQL: WideString;
out sPrvName: WideString);
var
par,tmp:OleVariant;
cnt:integer;
begin
//EnableCommit;
fDataSet.Close;
fDataSet.CommandText:=sSQl;
fDataSet.Open;
sPrvName:=fprovider.Name;
end;procedure TRDMCardServer.ExecuteData(const sSQL: WideString; out pResult,
pMsg: WideString);
var
par,tmp:OleVariant;
cnt:integer;
begin
//EnableCommit;
try
fcmd.CommandText:=sSQL;
fcmd.Execute;
pResult:='1';
except
pResult:='0';
end;
end;procedure TRDMCardServer.RollBackTrans(var pResult, pMsg: WideString);
begin
// SetAbort;
fconnection.RollBackTrans;
end;procedure TRDMCardServer.MtsDataModuleActivate(Sender: TObject);
var
Path: array[0..MAX_PATH] of Char;
Result,strPath: String;
begin
SetString(Result, Path, GetModuleFileName(HInstance, Path, SizeOf(Path)));
strPath:= ExtractFilePath(Result);
if not fConnection.Connected then
begin
fConnection.ConnectionString := 'FILE NAME=' + strPath + '\Local.UDL' ;
fConnection.Connected:=True;
end;
end;procedure TRDMCardServer.MtsDataModuleDeactivate(Sender: TObject);
begin
fConnection.Connected:=False;
end;initialization
TComponentFactory.Create(ComServer, TRDMCardServer,
Class_RDMCardServer, ciMultiInstance, tmBoth);
end.软件中间层只是简单传送了sql语句到数据库服务器,并没有处理业务逻辑,业务逻辑是在客户端通过事务来保证其完整正确性的。
中间层没起到实际作用,但是软件太庞大,不好改太多,我想只要客户端能控制事务也行,可是总是不能回滚。
请高手指点!
我看了com+个把星期了,还是蒙蒙懂懂!
有几个问题要注意:
1、跨Database的transaction因为没有DTC支持不行;
2、使用了状态,从池中取出后再使用时可能状态不对,如池化时还在InTransaction状态。
当我用SQL Server的企业管理器打开那些表时,表总是处于挂起状态,要等上一段时间,直到Com+组件释放了某些东西(我也不知到是什么东西)才能将表打开!
这样虽然解决了客户端控制事务的问题,但是如果是多个客户端同时并发执行,而某个正在执行数据库操作的客户端异常终止,导致某些表挂起,就有可能影响其它客户端程序的正常运行,我分析的对吗?如果是这样的这个问题该怎么解决啊?
procedure TRDMCardServer.BeginTrans(out pResult, pMsg: WideString);
begin
//EnableCommit;
//fconnection.BeginTrans;
fcmd.CommandText:='Begin Tran T1';
fcmd.Excute;
end;procedure TRDMCardServer.CommitTrans(out pResult, pMsg: WideString);
begin
//fconnection.CommitTrans;
//SetComplete;
fcmd.CommandText:='Commit Tran T1';
fcmd.Excute;
end; procedure TRDMCardServer.RollBackTrans(var pResult, pMsg: WideString);
begin
// SetAbort;
// fconnection.RollBackTrans;
fcmd.CommandText:='RollBack Tran T1';
fcmd.Excute;
end;