2

When I do ClientDataset.RefreshRecord, I get a runtime exception

Project DeMijn.exe raised exception class EDatabaseError with message 'Field 'MemberID' cannot be modified'.

The setup is

AdoQuery => DataSetProvider => ClientDataset

I have tried every possible combination of the provider flags on the persistent AdoQuery field, no result:

  • I tried it also with the persistent ClientDataset field, no result
  • In combination, every possible combination, no result
  • readonly = false
  • State = dsBrowse

The data provider has ResolveToDataSet true and poPropogateChanges true

I'm using:

  • Delphi 12 CE
  • SQL Server
  • MemberID is an identity column

What magic trick do I need to do a simple RefreshRecord ?

EDIT

The query has a join. The DataProvider has GetTableName set to the correct table

EDIT

I tried removing the field, removing the column from the dbgrid, still the same error.
I am trying out whatever now, desperate why this is not working.
Removing FieldName, setting flags empty, and so on...

Column := ColumnByName(SMDBGridList, PrimaryKeyName);    
SMDBGridList.Columns.Delete(Column.Index); 
Field := Column.Field; 
//Field.FieldName := ''; 
ggDataModule.ClientDataSetEntity.Fields.Remove(Field); 
// field.ProviderFlags := []; 
//Field.ReadOnly := false; 
//Field.Origin := ''; 
ggDataModule.ClientDataSetEntity.RefreshRecord;

Edit after debugging

I found that in unit DataSnap.Provider the field is assigned from Delta and there the field is ReadOnly for some reason.
See the code snipet below, from the vcl unit DataSnap.Provider.
In the last line of the code below, Delta.Fields[I].Assign(Field); seems to be a problem.
Field is readonly false but after the Assign it is readonly true because Delta.Fields[I] is readonly
Now this might be a clue, I just don't know how to fix this.

procedure TDataSetProvider.UpdateRecord(Source, Delta: TDataSet; BlobsOnly, KeyOnly: Boolean);
var
  Field: TField;
  I: Integer;
  UseUpMode: TUpdateMode;
  DS: TDataSet;
  UseFindRecord: Boolean;
begin
  if KeyOnly then
    UseUpMode := upWhereKeyOnly
  else
    UseUpMode := UpdateMode;
  UseFindRecord := ResolveToDataSet and not Source.IsUniDirectional;
  if not UseFindRecord then
    DS := TDataSetProvider(Resolver.Provider).GetDataSetFromDelta(
      Resolver.UpdateTree, Source, Delta, UseUpMode)
  else
  begin
    if not FindRecord(Source, Delta, UseUpMode) then
      DatabaseError(SRecordChanged);
    DS := Source;
  end;
  try
    Delta.Edit;
    for I := 0 to Delta.FieldCount - 1 do
    begin
      Field := DS.FindField(Delta.Fields[I].FieldName);
      if (Field <> nil) and (not (Field.Lookup or Field.Calculated)) and
         (not BlobsOnly or (Field.IsBlob and VarIsNull(Delta.Fields[I].NewValue))) then
        Delta.Fields[I].Assign(Field);

So I was hoping to do this

cdsDelta := ggDataModule.ClientDataSetEntity.Delta;

for i:= 0 to cdsDelta.FieldCount - 1 do
begin
  cdsDelta.Fields[i].readonly := false;
end;

but i get Delta is empty

1 Answer 1

0

I got around the problem by doing an old nasty trick.
I copied the unit DataSnap.Provider.pas into a seperate folder, and put that folder on top of the list in the SearchPath of the project, so that this copy is used instead of the original DataSnap.Provider.pas.
Now I altered the code in my copy on line 2711

if (Field <> nil) 
  and (not (Field.Lookup or Field.Calculated)) 
  and (not Delta.Fields[I].ReadOnly) // <-- THIS FIXES MY PROBLEM
  and (not BlobsOnly or (Field.IsBlob and VarIsNull(Delta.Fields[I].NewValue))) then
    Delta.Fields[I].Assign(Field);

Now it works, but I would still like to find a proper solution so I don't have to use this hack anymore. Because every update/new version of Delphi I might have to do this again...

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.