DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: melqui
今日帖子: 4
在线用户: 2
导航: 论坛 -> 数据库专区 斑竹:liumazi,waterstone  
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/27 10:40:17
标题:
求教:ClientModule1.SQLConnection1.StartTransaction为啥不起作用? 浏览:1302
加入我的收藏
楼主: 代码如下:
procedure TSys_Login_Fm.BitBtn2Click(Sender: TObject);
begin
  MainKJ_Fm.Close;
end;

procedure TSys_Login_Fm.Button1Click(Sender: TObject);
var sql:string;
var empname:string;
var TD:TTransactionDesc;
begin
  try
    TD.TransactionID:=1222;          
    TD.IsolationLevel:=xilREADCOMMITTED;      
    ClientModule1.SQLConnection1.StartTransaction(TD);   

    sql:=' use FcQYGL ';
    empname:='张三';
    sql:=sql+' insert into SysLoginSet (LoginUserName) values ('''+empname+''')  ';
    ClientModule1.execsql(3,sql);

    sql:=' use FcQYGL ';
    empname:='李四';
    sql:=sql+' insert into SysLoginSet (LoginUserName) values ('''+empname+''')  ';
    ClientModule1.execsql(3,sql);

    sql:=' use FcQYGL ';
    empname:='王五';
    sql:=sql+' insert into SysLoginSet (LoginUserName) values ('''+empname+''')  ';
    ClientModule1.execsql(3,sql);

    sql:=' use FcQYGL ';
    empname:='周六';
    sql:=sql+' insert into SysLoginSet (LoginUserName1) values ('''+empname+''')  ';
    ClientModule1.execsql(3,sql);


    ClientModule1.SQLConnection1.Commit(TD);

     showmessage('执行完毕!');
  except
    On E:Exception do
    begin
     ClientModule1.SQLConnection1.Rollback(TD) ;

     Application.MessageBox(PChar(E.Message), '错误', 16);//抛出异常信息
    end;
  end;
end;

在插入‘周六’时故意把字段写错,LoginUserName1(应该为LoginUserName)
执行后,提示字段错误,但是,前面的三条记录仍旧被写入数据库并没有Rollback

请问:
 
    ClientModule1.SQLConnection1.StartTransaction(TD);  
具体应该如何实现?
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/27 13:22:19
1楼: function TClientMOdule1.execsql(ExeType:Integer;sql: string): string;
begin
//  简单查询使用       1
//  简单更新使用       2
//  需要事务更新使用   3
    if ExeType=1 then
    begin
      ClientDataSet1.Close;
      ClientDataSet1.CommandText:=sql;
      ClientDataSet1.Open;
    end else if ExeType=2 then
    begin
      ClientDataSet1.Close;
      ClientDataSet1.CommandText:=sql;
      ClientDataSet1.Execute;
    end else if ExeType=3 then
    begin
      ClientDataSet1.Close;
      ClientDataSet1.CommandText:=sql;
      ClientDataSet1.Execute;
    end;
    Result:='0';
end;
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 1:45:51
2楼: first:
1) why you try idendify the "ID" transaction ?
---> this should be done by "database", NOT YOU!!!

2) SQLConnection1.StartTransaction( n )
---> Note: StartTransaction has been deprecated.
------> Use BeginTransaction instead. // EndTransaction!

try some like this:

procedure TForm1.Button2Click(Sender: TObject);
var
  MyDBXTransaction: TDBXTransaction;
begin
  if not SQLConnection1.InTransaction then
    begin
      try
        MyDBXTransaction := SQLConnection1.BeginTransaction;
        //
        // .... ClientDataset post...
        //
        SQLConnection1.CommitFreeAndNil(MyDBXTransaction);
      except
        SQLConnection1.RollbackFreeAndNil(MyDBXTransaction);
      end;
    end;
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 1:52:35
3楼: you ca do it some like:

type
  TMySQLText = array [0 .. 2] of String;

const
  MySQLText: TMySQLText = ('sql 1', 'sql 2', 'sql 3');

function ChoiceASQLForUsage(const AChoice:integer) : string;
begin
  result := '';
  //
  if (AChoice in [0 .. 2]) then
    result := MySQLText[MySQLChoiced];
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 1:53:42
4楼: THIS methods IS DEPRECATED USAGE: DONT USE IT ANYMORE
- ClientModule1.SQLConnection1.Commit(TD);
- ClientModule1.SQLConnection1.Rollback(TD) ;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 1:58:58
5楼: MySQLText: TMySQLText = (
'select * from TableX where ID=%d',     // to integer values
'select * from TableX where name=%s',  // to string values
'select * from TableX where fieldX=%s'  // ....
);

...
if (MySQL<>'') then
  ShowMessage( Format(MySQL, [ ValueXXXX_type_expected ] ) );
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 3:44:11
6楼: ClientDataSet1.CommandText:=sql;
ClientDataSet1.Execute; // insert, delete, update, alter, etc...

ClientDataSet1.CommandText:=sql;
ClientDataSet1.Open; // select
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 10:01:35
7楼: emailx45 (emailx45),谢谢,我试试
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 10:30:51
8楼: 按照:
first:
1) why you try idendify the "ID" transaction ?
---> this should be done by "database", NOT YOU!!!

2) SQLConnection1.StartTransaction( n )
---> Note: StartTransaction has been deprecated.
------> Use BeginTransaction instead. // EndTransaction!

try some like this:

procedure TForm1.Button2Click(Sender: TObject);
var
  MyDBXTransaction: TDBXTransaction;
begin
  if not SQLConnection1.InTransaction then
    begin
      try
        MyDBXTransaction := SQLConnection1.BeginTransaction;
        //
        // .... ClientDataset post...
        //
        SQLConnection1.CommitFreeAndNil(MyDBXTransaction);
      except
        SQLConnection1.RollbackFreeAndNil(MyDBXTransaction);
      end;
    end;
end;
出现:
此帖子包含附件:
PNG 图像
大小:2,011B
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 11:08:21
9楼: 跟踪发现:MyDBXTransaction 为nil
是哪里的问题呢?
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 11:18:56
10楼: my fault:

try this:
uses
  Data.DBXCommon;

// TDBXIsolations see on HELP!!!

SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted)
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 11:27:07
11楼: uses Data.DBXCommon   已加
SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted)试了试,
MyDBXTransaction 的值还是nil
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2022/11/28 12:16:06
12楼: the ClientDataset is Open? You ClientDataset is using your SQLConn?
----------

dbxTR := SQLCon.BeginTransaction(TDBXIsolations.ReadCommitted);

SQLCon.Execute('your sql',your-params);

SQLcon.CommitFreeAndNil(dbxTR);
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 12:22:24
13楼: DataSnap  -->  SQLConnection1  
--> DSProviderConnection1  -->ClientDataSet1
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 13:00:49
14楼: ClientDataSet(snap三层) 本身有事务机制,但是,每次必须把所有的SQL语句一次性的去执行,这个我也试验过,的确如此。缺点是导致必须把所有的语句都加在一起,统一执行,很不方便

所以,我觉得还是自己控制事务的开始与提交比较方便

可是,可是。。。。。。。。。。
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/11/28 13:41:59
15楼: 14 楼,你说的情况,是指 ClientDataSet.ApplyUpdates 的情况。

对于这种情况,如果你有多个表要提交,又分2种情况:

1. 如果这几个表本身是主从关系,你直接在服务器端做嵌套式的主从表,到客户端,只需要一个 ClientDataSet 需要提交。因此,这几个表的提交也同样是在一个事务里面。

2. 那几个表是不相关的表,数据通过 join 的方式合成了一个表,在客户端虽然对应的是一个 ClientDataSet 但在服务器端显然不是一个 Query 能搞定的,需要自己在服务器端写代码;

--------
不管如何,你在服务器端采用你主贴里的那种方式:

StartTransaction;
try
  do。。。。

  Commit;
except
  RollBack;
end;

采用上述框架,是可以保证事务的。

如果你的代码采用上述框架不能保证事务,你要做一个检测,它是否已经有一个事务还没提交。

另外,你的代码里面是:ClientModule1.execsql(3,sql);

那么,你要检查这个 ClientModule1.execsql(3,sql); 本身是否有处理事务。
----------------------------------------------
-
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 16:19:42
16楼: ClientModule1.execsql(3,sql)
begin
      ClientDataSet1.Close;
      ClientDataSet1.CommandText:=sql;
      ClientDataSet1.Open;
end;
不存在事务的,另外:ClientDataSet.ApplyUpdates是什么机制?
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/11/28 17:33:42
17楼: 16 楼,如果你用 Delphi 自己的基于 MIDAS 的 3 层架构,比如早期的基于 DCOM,或者基于 Socket 的那个,或者是后来的基于 WebService 的,因为 Delphi 已经帮你把中间的代码写好了,你自己的客户端和服务器端之间的连接是基于 Delphi 的框架提供的,服务器端是 ADOQuery 或者 Fdquery,加上一个 DataSetProvider 输出数据,客户端就是一个 ClientdataSet,在这样的架构下,客户端:

ClientDataSet.Open; 就自动从服务器端获得数据了;
ClientDataSet.ApplyUpdates 就自动把修改后的数据提交给服务器端了。

当然,现在最新版的 Delphi 提供了新的 DataSnap 的3层架构,已经不是基于 MIDAS 的架构了,客户端也不要求是 ClientDataSet 了,而要求是 FdMemTable。玩法就不一样了。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/11/28 17:42:58
18楼: 至于事务,楼主你的问题就非常简单了:

你在一个事务里面,执行了多次 ClientModule1.execsql(3,sql),而这个 ClientModule1.execsql(3,sql) 里面,你其实是做了 ClientDataSet1.Open;

你要知道,ClientDataSet 每次操作都会有自己的事务。因此,你做的那个事务里面包含了很多个事务,除非你的数据库支持事务嵌套。

因此,楼主你的问题其实非常简单,在服务器端,你就不应该使用 ClientDataSet1.Open; 的办法去执行 SQL。事务这个玩意是在服务器端执行的,不是在客户端执行的。我看你的代码,看不懂你究竟是在客户端调用事务,还是在服务器端调用事务。

如果你是在服务器端调用事务,那你在服务器端,应该是使用 FdQuery 或者 ADOQuery 之类的直接操作数据库的控件才对。

至于客户端,你只需要调用服务器端的函数,把参数传递过去。

代码类似:

TMyServer.SaveMyData(MyData: Txxxx);
begin
  开始事务
  try
    ADOQuery1.SQL := 'update xxx ';
    ADOQuery1.Params[0].Value := MyData.AAAA
    ADOQuery1.ExecSQL;

    FdQuery2.SQL := 'Deletel xxxx where ID=:bbb';
    FDQueyr2.Params['bbb'].Value := MyData.bbb;
    FDQuery2.ExecSQL;
    Commit;
  except
    RollBack;
  end;

end;


在客户端,你只需要调用服务器端的这个函数:

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyData := Txxx.Create;

  MyServer.SaveMyData(MyData);
end;


不管你用什么样的三层架构,大概的基本概念应该是这样。

你主贴的那种写法,事务工作不正常,就是很好理解的了。
----------------------------------------------
-
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2022/11/28 18:10:01
19楼: pcplayer (pcplayer)
透彻,谢谢!
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行83.98438毫秒 RSS