Delta问题(50分)

  • 主题发起人 主题发起人 lgh200
  • 开始时间 开始时间
L

lgh200

Unregistered / Unconfirmed
GUEST, unregistred user!
我做了一个三层结构,应用服务器用ado连接。
在客户端,我把一个clientdataset的delta的值赋给另一个clientdataset的data,
发现原记录的某些字段的值发生了改变,请问有什么方法解决。(我们都知道,delta
中即有原始记录,又有修改后的记录,我发现delta中的原始记录中某些字段值也发生
了改变,与数据库中的不一样)
 
怎么不一样了?
 
delta的文件格式好像没有公开吧
 
例如数据库中记录如下
234 李国华 男
我修改记录中的姓名以后,delta的记录如下:
0 李国华 男 234 变成 0 了。
李国
 
应该不会有这种事?
会不会是数据库的记录变了?
 
我做了一个例子,但是,没有出现你的情况,是不是第一个字段值你改动了,所以变成0了?
 
应该不会,我也用delta自己处理数据提交,没出过问题。
 
真奇怪啊,我只是把delta的值赋给另外一个TClientDataSet,然后显示,就出现上面
的问题了。是不是我的ADO设置有问题啊,我用bde的话就不会出现上面的问题。
 
Delta中存的只是修改过的数据,你没有修改那个字段
 
谁知道Delta的格式啊,lgh200说得问题我也遇到了,也就是说修改一次造成Delta中的两条记录,一条是原始的,一条是除了修改的字段之外都是空值的
 
很可能是在你修改后,数据库表被修改了,出现你说的这种不一致情况
 
delta应该就是clientdataset的格式,可以用fieldbyname访问。
如果是改过的字段,可以用.value取当前值,.oldvalue取修改前的值。
如果是没改过的字段,.value自然是没有值的,.oldvalue是当前值。
 
这个不可能,我是单机测试,保证只有一个修改可能,而且我并没有提交ApplyUpdate,这时候和数据库是没有任何关系的,我对Save写了一小段测试程序,使用DBGrid把Delta的内容显示出来,规律是,对于删除的记录,在Delta中出现一条同样的记录,对于修改一个字段的记录,Delta中出现两条记录,一条是完整的记录和一个对应修改字段旧值的其它未修改字段为空的记录,使用NewValue和OldValue对Delta访问都是NULL
 
在多表更新这个经典问题上,我想采用跟踪Delta变化来处理,可是不知道Delta的格式,例如变化的信息都有了,我们能不能知道这些记录谁是删除的,谁是更新的,谁是添加的,如果知道,我们就能够采用一种通用方法来解决,不用在AppServer上面设置什么Unique Table之类的东西了
 
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;
 
ADOQUERY.ENABLEBCD := FALSE;
 
后退
顶部