三层的applyupdate问题(100分)

  • 主题发起人 主题发起人 迷失者
  • 开始时间 开始时间

迷失者

Unregistered / Unconfirmed
GUEST, unregistred user!
小弟有一段代码,功能是用户在客户端编辑数据,然后提交
c_begin
trans;//在客户断启动事物
try
applyupdate(0);
......//这里有一些对刚提交的数据进行检查等的函数,还有一些杂七杂八的影响数据库
的函数,如果中间有异常或者发现数据不合法就会回滚
c_commit;
except
c_rollback;//客户端回滚事物
end;

本身看起来没什么问题,但如果上面applyupdate之后, commit之前出现异常,回滚
然后用户修改提交的数据重新提交这时候在applyupdate之后回连报三个错误。(在调试
时候,服务器程序报错)
missing SQL property
unable to resolve records.table name not found
unable to find record.no key specified.
我想可能是第一次提交的时候,clientdataset datasetprovider ,ADoquery之间连接断开
了,或者是原有的SQL语句被清空了,可到底是怎么回事不清楚,尤其是该怎么解决不清楚。
大虾们,救命啊!
 
服务器的Tquery sql语句可能被你清空了.
接下来,的问题就是由于缺乏sql语句引起的,而且你更新模式是用到key作为定位对象.
 
你的commit/rollback和数据检查为什么不写到服务端呢?
这样子客户端想瘦也不行了……
 
中間層的Tquery sql语句可能被你清空了.
你的commit/rollback和数据检查为什么不写到中間層呢?
 
因为要提交的clientdataset是在客户端客户编辑的,所以必须在客户端提交,而提交之前
必须开启事务,而且应该是在客户端开始,至于数据检查我也是调用中间层的程序而已,如果只有一个sql语句的检查我也懒得放服务器,客户端运行一下应该也不影响速度。但主要的问题是sql语句丢失的问题怎么解决?
我出现的问题是,由于提交客户端数据集,而不太好在中间层开启事务。至于检查数据
放中间层,已经是放在中间层了,或者很少sql语句的检查就没有放,关键是检查sql语句
放在中间层也解决不了回滚后sql语句的丢失问题啊!
 
客户端是怎么启动事物的.如果是在IAPPSERVER中定义函数,SQL语句做为传入参数然后调用TDATABASE的事物处理我还能想到,你要直接启用事物处理,我很迷惑
 
找一下第出錯以後的SQL是否真的丟失掉。
 
把你的SQL语句贴出来看看,事务还是放在服务端好
试试在DataSetProvider.OnGetTableName中指定TableName
 
看各位老兄为了三层累的半死,贴一段 代码,参考一下吧,别写那么多
重复代码,多分析,什么都好解决的!!!
function TuaServerObject.SubmitDelta(lAdoConn:TAdoConnection;sTblName:string;cdsSrc:TClientDataSet;
lFieldKeys:array of string;UpdateType:TUAUpdateTypes;
iFailMax:integer;var uaOut:TUAUpdateDataOutPacket):integer;
var
i,j,iOrgCount,iNpOutIndex:integer;
lField:TField;
sSql,s1,sSqlSelect:string;
v1:variant;
adoU:TAdoCommand;
bContinue:Boolean;
cdsDest:TClientDataSet;
adoSelect:TAdoDataSet;
UpdateError:TUAUpdateErrorCode;
aErrorParam:TErrorParam;
sErrorMsg:string;
sErrorContext:string;
aErrorCDS:TClientDataSet;
sNativeErrorMsg:string;
bAtHandle,bBtHandle:Boolean;
begin

sNativeErrorMsg := 'Native Error Information Is :';
bAtHandle := false;
bBtHandle := false;
Result := 0;
adoU := nil;
adoU := TAdoCommand.Create(nil);
cdsDest := nil;
cdsDest := TClientDataSet.Create(nil);
aErrorCDS := TClientDataSet.Create(nil);
try
cdsDest.FieldDefs.Clear;
for i :=0 to cdsSrc.FieldDefs.Count -1do
begin
with cdsDest.FieldDefs.AddFieldDefdo
begin
Name := cdsSrc.FieldDefs.Name;
DataType := cdsSrc.FieldDefs.DataType;
Size := cdsSrc.FieldDefs.Size;
Precision := cdsSrc.FieldDefs.Size;
Attributes := cdsSrc.FieldDefs.Attributes;
Required := cdsSrc.FieldDefs.Required;
end;
end;
cdsDest.CreateDataSet;
adoU.Connection := lAdoConn;
adoU.CommandText :='';
bContinue := true;
cdsSrc.First;
while (not cdsSrc.Eof) and bContinuedo
begin
if trim(sNativeErrorMsg) <> '' then
sNativeErrorMsg := sNativeErrorMsg + #13;
cdsDest.Insert;
for i :=0 to cdsSrc.FieldCount -1do
cdsDest.Fields.Value := cdsSrc.Fields.Value;
case cdsSrc.UpdateStatus of
usUnmodified:
begin
cdsSrc.Next;
sSql := ' Update '+sTblName+' Set ';
s1 := '';
for j := 0 to cdsSrc.FieldCount -1do
begin
v1 := cdsSrc.Fields[j].Value;
if not VarIsNull(v1) then
begin
if s1<>'' then
s1 := s1 +',';
s1 := s1 + cdsSrc.Fields[j].FieldName+ ' = ';
s1 := s1 + FieldValueToSqlStr(cdsSrc.Fields[j].DataType,v1);
end;
end;
sSql := sSql +' '+s1 + ' Where ';
for j := 0 to cdsDest.FieldCount -1do
begin
v1 := cdsDest.Fields[j].Value;
if j>0 then
sSql := sSql +' and ';
if not VarIsNull(v1) then
begin
sSql := sSql + cdsDest.Fields[j].FieldName+ ' = ';
sSql := sSql + FieldValueToSqlStr(cdsDest.Fields[j].DataType,v1);
sSql := sSql +' ';
end else
begin
sSql := sSql + cdsDest.Fields[j].FieldName + ' Is Null ';
end;
end;

sSqlSelect := GenSelectDS(sTblName,cdsDest,lFieldKeys);
UpdateError := ueOk;
adoSelect := TAdoDataSet.Create(nil);
try
adoSelect.Connection := lAdoConn;
adoSelect.CommandText := sSqlSelect;
adoSelect.Open;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
Inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpdateError := ueSelectSql;
end;
end;

iOrgCount := adoSelect.RecordCount;
if UpdateError = ueOk then
begin
if iOrgCount =0 then
begin
UpDateError := ueModChanged;
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
end
else
if iOrgCount=1 then
begin
try
adoU.CommandText := sSql;
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
UpDateError := ueOk;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueModOneSql;
end;
end;
end
else
begin
if upModifyOne in UpdateType then
begin
Inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueModOneButMany;
end
else
begin
try
adoU.CommandText := sSql;
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
///???
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
UpDateError :=ueOk;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
Inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpdateError := ueModManySql;
end;
end;
end;
end;
end;
if UpdateError <>ueOk then
begin

//修改数据不成功,返回调用异常
//异常消息+数据包
aErrorParam := TErrorParam.Create;
aErrorParam.ErrorCode := $FA01;
{$ifdef CHNDEBUG}
sErrorMsg := '修改数据库记录发生错误!';
{$else
}
sErrorMsg := 'error on modify record!';
{$endif}
aErrorParam.ErrorMsg := sErrorMsg + #13#10 + sNativeErrorMsg;
aErrorParam.ErrorContext := TUAUpdateErrorMsg[Ord((updateError))] +#13#10+ 'Sql Script Is:' + sSql ;
uaOut.AddItemErrorParam(aErrorParam);
cdsDest.Append;
for j :=0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := adoSelect.fieldByName(cdsDest.Fields[j].FieldName).value;
cdsDest.Append;
for j := 0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := cdsSrc.Fields[j].Value;
aErrorCDS.AppendData(cdsDest.Data,false);
end;
FreeAndNil(adoSelect);
cdsDest.first;
for j := 1 to cdsDest.RecordCountdo
cdsDest.Delete;
end;

usInserted:
begin
sSql := 'insert into '+ sTblName+'(';
s1 :='';
for j := 0 to cdsSrc.Fields.Count -1do
begin
v1 := cdsSrc.Fields[j].Value;
if not VarIsNull(v1) then
begin
if s1<>'' then
begin
sSql := sSql+',';
s1 := s1 +',';
end;
sSql := sSql +cdsSrc.Fields[j].FieldName;
s1 := s1 + FieldValueToSqlStr(cdsSrc.Fields[j].DataType,v1);
end;
end;
if s1<>'' then
begin
sSql := sSql +')';
s1 := s1 +')';
sSql := sSql+ ' values (' +s1;
sSqlSelect := GenSelectDS(sTblName,cdsDest,lFieldKeys);
UpdateError := ueOk;
adoSelect := TAdoDataSet.Create(nil);
try
adoSelect.Connection := lAdoConn;
adoSelect.CommandText := sSqlSelect;
adoSelect.Open;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
Inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpdateError := ueSelectSql;
end;
end;

iOrgCount := adoSelect.RecordCount;
if UpdateError = ueOk then
begin
if iOrgCount =0 then
begin
try
adoU.CommandText := sSql;
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueInsSql;
end;
end;
end
else
if iOrgCount>=1 then
begin
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueInsExit;
end;
end;
if UpdateError <>ueOk then
begin

//新增数据不成功,返回调用异常
//异常消息+数据包
aErrorParam := TErrorParam.Create;
aErrorParam.ErrorCode := $FA02;
{$ifdef CHNDEBUG}
sErrorMsg := '新增数据库记录发生错误!';
{$else
}
sErrorMsg := 'error on insert record to table!';
{$endif}
aErrorParam.ErrorMsg := sErrorMsg + #13#10 + sNativeErrorMsg;
aErrorParam.ErrorContext := TUAUpdateErrorMsg[Ord((updateError))] +#13#10+ 'Sql Script Is:' + sSql;
uaOut.AddItemErrorParam(aErrorParam);
cdsDest.Append;
for j :=0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := adoSelect.fieldByName(cdsDest.Fields[j].FieldName).value;
cdsDest.Append;
for j := 0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := cdsSrc.Fields[j].Value;
aErrorCDS.AppendData(cdsDest.Data,false);
end;
FreeAndNil(adoSelect);
cdsDest.first;
for j := 1 to cdsDest.RecordCountdo
cdsDest.Delete;
end;
end;

usDeleted:
begin
sSql := 'delete '+ sTblName+' where ';
for j :=0 to cdsSrc.Fields.Count -1do
begin
v1 := cdsSrc.Fields[j].Value;
if j >0 then
sSql := sSql +' and ';
if not VarIsNull(v1) then
begin
sSql := sSql +cdsSrc.Fields[j].FieldName +' = ';
sSql := sSql +FieldValueToSqlStr(cdsSrc.Fields[j].datatype,v1);
end
else
begin
sSql := sSql +cdsSrc.Fields[j].FieldName + ' Is Null ';
end;
end;
UpdateError := ueOk;
sSqlSelect := GenSelectDS(sTblName,cdsDest,lFieldKeys);
adoSelect := TAdoDataSet.Create(nil);
try
adoSelect.Connection := lAdoConn;
adoSelect.CommandText := sSqlSelect;
adoSelect.Open;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
Inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpdateError := ueSelectSql;
end;
end;
iOrgCount := adoSelect.RecordCount;
if UpdateError = ueOk then
begin
if iOrgCount =0 then
begin
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueDelNonExit;
end
else
if iOrgCount=1 then
begin
try
adoU.CommandText := sSql;
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
UpDateError := ueOK;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueDelOneSql;
end;
end;
end
else
begin
if upDeleteOne in UpdateType then
begin
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueDelOneButMany;
end
else
begin
try
adoU.CommandText := sSql;
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
UpDateError := ueOK;
except
on E:Exceptiondo
begin
sNativeErrorMsg := sNativeErrorMsg +E.Message;
inc(Result);
if (iFailMax>0) and (Result >= iFailMax) then
bContinue := false;
UpDateError := ueDelManySql;
end;
end;
end;
end;
end;
if UpdateError <>ueOk then
begin
//删除数据不成功,返回调用异常
//异常消息+数据包
aErrorParam := TErrorParam.Create;
aErrorParam.ErrorCode := $FA03;
{$ifdef CHNDEBUG}
sErrorMsg := '删除数据库记录发生错误!';
{$else
}
sErrorMsg := 'error on delete record from table!';
{$endif}
aErrorParam.ErrorMsg := sErrorMsg + #13#10 + sNativeErrorMsg;
aErrorParam.ErrorContext := TUAUpdateErrorMsg[Ord((updateError))] +#13#10+ 'Sql Script Is:' + sSql;
uaOut.AddItemErrorParam(aErrorParam);
cdsDest.Append;
for j :=0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := adoSelect.fieldByName(cdsDest.Fields[j].FieldName).value;
cdsDest.Append;
for j := 0 to cdsDest.Fields.Count -1do
cdsDest.Fields[j].Value := cdsSrc.Fields[j].Value;
aErrorCDS.AppendData(cdsDest.Data,false);
end;
FreeAndNil(adoSelect);
cdsDest.first;
for j := 1 to cdsDest.RecordCountdo
cdsDest.Delete;
end;
end;
cdsSrc.Next;
end;
finally
if Assigned(adoU) then
FreeAndNil(adoU);
if Assigned(cdsDest) then
FreeAndNil(cdsDest);
if Assigned(aErrorCDS) then
FreeAndNil(aErrorCDS);
end;

end;
 
这两天没上网,多了这一段代码,我先研究一下,不知道能不能解决我说的问题
 
不行啊,上面的代码好象和我说的问题没有关系啊
再详细的说一下代码吧
//在客户断启动事物
procedure C_begin
Trans:boolean;
begin
DCOMConnection1.AppServer.begin
Trans;
end;

procedure C_CommitTrans;
begin
DCOMConnection1.AppServer.CommitTrans;
end;

procedure C_Rollback;
begin
DCOMConnection1.AppServer.RollbackTrans;
end;

//server的启动事物函数
function TServerRDM.begin
Trans: WordBool;
begin
ADOConnection1.begin
Trans;
end;

procedure TServerRDM.CommitTrans;
begin
ADOConnection1.CommitTrans;
end;

procedure TServerRDM.RollbackTrans;
begin
ADOConnection1.RollbackTrans;
end;

procedure initCDS;
begin
customerCDS.close;
customerCDS.CommandText:='select * from persontable ';
customerCDS.open;
end;

procedure modifyclick;
begin
customerCDS.edit;
end;

procedure insertclick;
begin
customerCDS.append;
end;

procedure updatedata;
begin
try
c_begin
trans;
customerCDS.applyupdate(0);
clientdataset1.close;
clientdataset1.CommandText:='select name from persontable where name is not null group by name having count(name)>1';
clientdataset1.open;
if clientdataset1.recordcount>0 then
begin
c_rollback;
showmessage('名称不能重复!');
end
else
c_commit;
except
c_rollback;//客户端回滚事物
end;
end;

几个调用server的事物,initCDS是初始化读出表中数据,
用户可以编辑(edit),添加(append)
到保存的时候调用 updatedata;
我只是举了一个sql语句来说明我的意图。
这个检查sql语句其实就是检查一下当前编辑后的数据提交后,有没有重复的name存在
如果有回滚编辑无效修改后提交,当修改后没有重复name的时候再次提交就回出现我第一篇
说的错误。
我查过了再次提交的时候客户端的customerCDS.CommandText是没有错的好象是说我
服务器上的ADOQuery的sql语句没有了。
希望各位大侠给我分析分析原因找找解决方法
别说一定要我不用这种方法。就本例而言我当然知道可以在applyupdate之前检查客户端的
name数据,但一来效率不高,二来这种方法一个sql语句方便,最主要的是别的地方我有不同原因都是类似这样检察,或者说我想如果applyupdate本身出错按我的事物写法估计再次提交的时候还是有一样的问题。
我该怎么办?

 
BeforeTriggerForDataSet(sTblName,adoSelect,cdsDest,bBtHandle);
///???
adoU.Execute;
AfterTriggerForDataSet(sTblName,adoSelect,cdsDest,bAtHandle);
兄弟,你好好看一下我的代码,我已经在这个处理中支持到数据行的触发处理,
那么你的问题也就不成问题了!
 
不好意思,问题找到了是一同事在rollback后的一个函数里面加了一个断开connection,
藏的很深,他也是忘记有这么个代码,
 

Similar threads

S
回复
0
查看
730
SUNSTONE的Delphi笔记
S
S
回复
0
查看
738
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部