Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Midas/TClientDataSet    [ Add a report in this area ]  
Report #:  4508   Status: Closed
ChangeCount being incremented when data has not changed.
Project:  Delphi Build #:  7.0.4.453
Version:    7.0 Submitted By:   Dave Rowntree
Report Type:  Basic functionality failure Date Reported:  5/20/2003 11:39:23 AM
Severity:    Serious / Highly visible problem Last Updated: 10/6/2006 6:51:00 AM
Platform:    95, 98, 2000, NT, XP Internal Tracking #:   167223
Resolution: Fixed (Resolution Comments) Resolved in Build: : 7.0.8.1
Duplicate of:  None
Voting and Rating
Overall Rating: (1 Total Rating)
5.00 out of 5
Total Votes: 1
Description
ChangeCount being incremented when data has not changed.

If a CDS TStringField or a TWideStringField containing only a few characters, has it's current data value re-entered, then posted, the CDS conciders a data change has occured and increments the ChangeCount. This is incorrect. A Delta is created where the changes indicated in the ukModified Delta record are identical to the original values.

If the CDS is being provided from a dbExpress data access layer against a MySQL database, the dbexpress problem described in QC#4504 will cause a 'Record not found or changed by another user' error when CDS.ApplyUpdates(0) is called.
Steps to Reproduce:
1. Download the test case app from Attachments.
2. The Tables.zip file contains the three files for the MySQL table which should be copied into your MySQL\Data\test directory.
3. The Tables.zip also contains an SQL script file for creating the required table in MSSQL.
4. Open the test case app in Delphi.
5. Alter the MSSQL connection component to point to the appropriate database.
6. Run the app in Delphi.
7. Follow the on screen instructions.
Workarounds
PROVIDER.PAS
(**) (* Delphi 6.0 - 7.0 *)
(* QC#4508 workaround. Prevents attempted DB updates where the field
   values have not changed in TStringField and/or TWideStringField.
NOTE: IF YOU USE THIS FIX YOU *MUST* ALSO USE MY FIX AGAINST QC#2338 (in Provider.pas) *)
(* Dave Rowntree 05/29/03 *)
function TCustomResolver.InternalUpdateRecord(Tree: TUpdateTree): Boolean;
var
  RecNoSave: Integer;
  Applied: Boolean;
  UpdateKind: TUpdateKind;
  E: Exception;
  PrevErr, Err: EUpdateError;
  i: integer; (* add this line *)
  v: variant; (* add this line *)
begin
  PrevErr := nil;
  Err := nil;
  Tree.Delta.UseCurValues := False;
  while True do
  try
    UpdateKind := Tree.Delta.UpdateKind;
    if ((UpdateKind = ukInsert) and (FPrevResponse in [rrMerge, rrApply])) or
       ((FPrevResponse = rrMerge) and Tree.Delta.HasMergeConflicts) then
      DatabaseError(SInvalidResponse);
    Applied := False;

    // check that no update TStringFields/TWideStringFields with unchanged values
    // check that no update TStringFields/TWideStringFields with unchanged values
    // exist in the Delta for ukModify ...
    if UpdateKind = ukModify then           (* add this line *)
      with Tree.Delta do                    (* add this line *)
        for i := 0 to Fieldcount -1 do      (* add this line *)
          if Fields[i].DataType in [ftString, ftWideString] then (* add this line *)
          begin                                                  (* add this line *)
            v := Fields[i].NewValue;                             (* add this line *)
            if not VarIsEmpty(v) and (v = Fields[i].OldValue) then (* add this line *)
              DSBase.PutBlank(ActiveBuffer,0,Fields[i].Index+1,BLANK_NOTCHANGED); (* add this line *)
          end; (* add this line *)


    RecNoSave := Tree.Delta.RecNo;
    try
      if Assigned(Provider.BeforeUpdateRecord) then
        Provider.BeforeUpdateRecord(Provider, Tree.Source, Tree.Delta, UpdateKind, Applied);
    finally

---------

PROVIDER.PAS
(**) (* Delphi 6.0 - 7.0 *)
(* QC#4508 workaround. Prevents attempted DB updates where the field
   values have not changed in TStringField and/or TWideStringField.
NOTE: IF YOU USE THIS FIX YOU *MUST* ALSO USE MY FIX AGAINST QC#2338 (in Provider.pas) *)
(* Dave Rowntree 05/29/03 *)
function TCustomResolver.InternalUpdateRecord(Tree: TUpdateTree): Boolean;
var
  RecNoSave: Integer;
  Applied: Boolean;
  UpdateKind: TUpdateKind;
  E: Exception;
  PrevErr, Err: EUpdateError;
  i: integer; (* add this line *)
  v: variant; (* add this line *)
begin
  PrevErr := nil;
  Err := nil;
  Tree.Delta.UseCurValues := False;
  while True do
  try
    UpdateKind := Tree.Delta.UpdateKind;
    if ((UpdateKind = ukInsert) and (FPrevResponse in [rrMerge, rrApply])) or
       ((FPrevResponse = rrMerge) and Tree.Delta.HasMergeConflicts) then
      DatabaseError(SInvalidResponse);
    Applied := False;

    // check that no update TStringFields/TWideStringFields with unchanged values
    // exist in the Delta ...
    with Tree.Delta do                    (* add this line *)
      for i := 0 to Fieldcount -1 do      (* add this line *)
        if Fields[i].DataType in [ftString, ftWideString] then (* add this line *)
        begin                                                  (* add this line *)
          v := Fields[i].NewValue;                             (* add this line *)
          if not VarIsEmpty(v) and (v = Fields[i].OldValue) then (* add this line *)
            DSBase.PutBlank(ActiveBuffer,0,Fields[i].Index+1,BLANK_NOTCHANGED); (* add this line *)
        end; (* add this line *)


    RecNoSave := Tree.Delta.RecNo;
    try
      if Assigned(Provider.BeforeUpdateRecord) then
        Provider.BeforeUpdateRecord(Provider, Tree.Source, Tree.Delta, UpdateKind, Applied);
    finally
Attachment
4508.zip
Comments

Tarvo Hirs at 5/21/2003 3:32:13 AM -
Seems like a classic case to me, not only a CDS specific feature.

How about this workaround:

if cdsStringField1.AsString <> newValue then
begin
  cds.Edit;
  cdsStringField1.AsString:= newValue;
  cds.Post;
end;

Dave Rowntree at 5/22/2003 3:24:47 AM -
Tarvo Hirs said - "Seems like a classic case to me"

Not really, no.

" not only a CDS specific feature.
"

This is a very CDS specific problem. The Midas.dll is incorrectly determining whether a change has occured to a field value.

Dave Rowntree at 5/11/2004 3:29:59 AM -
Fixed in Midas.dll

Server Response from: CODE1