Setting Null value using LINQ (fix to #67963)

Hi,

I was wondering if it possible to get the code that was changed with fix #67963. I have the following situation. I’m having the same issue as this question:

The problem I’m having is that I’m in the middle of migrating our app from Delphi 7/XE (client is in D7 and server is in XE) and RO/DA version 6.0.45.821, to Delphi 10, RO/DA version 8.3.91.1167. I still have a long way to go on this migration, so I’m stuck with version 6.0.45.821 on the server side. And I’m working on a new ASP.NET MVC web app that is using version 8.3.91.1167 with LINQ against the Delphi 6.0.45.821 server, but I’m seeing that null values are not being changed on the server.

So if I could get the changes made for this fix, perhaps I could implement those changes in our 6.0.45.821 server and get this problem out of the way.

Thanks,
Arturo.

Hello,
we received following email from support regarding this issue:

Please follow the next steps to fix the problem:

  1. Donwload and install RemObjects Oxygene at Oxygene: Modern Cross-platform Object Pascal | RemObjects Software . It will allow to open open and modify RemObjects DataAbstract sources.
  2. Follow instructions from Documentation | RemObjects Software to allow rebuild RemObjects DataAbstract assemblies
  3. Open RemObjects DataAbstract solution and change Delta.pas file from:
method Delta.RemoveUnnecessaryChanges();
 function IsNotRealChange(change: DeltaChange): Boolean;
  begin
    if not ((change.Status = ChangeStatus.Pending) and (change.Type = ChangeType.Update)) then
      exit false;
   for i: Int32 := 0 to change.Count-1 do begin
      if assigned(change.NewValues[i]) then begin
        if not change.NewValues[i].Equals(change.OldValues[i]) then
          exit false;
      end
      else begin
        if assigned(change.OldValues[i]) then
          exit false;
      end;
    end;
   exit true;
  end;
begin
  var lToDelete: System.Collections.Generic.List<DeltaChange> := new System.Collections.Generic.List<DeltaChange>;
  for each lChange: DeltaChange in Self.Items do begin
    if IsNotRealChange(lChange) then lToDelete.Add(lChange);
  end;
 for each lChange: DeltaChange in lToDelete do
      Self.Items.Remove(lChange);
end;

to

method Delta.RemoveUnnecessaryChanges();
 function IsNotRealChange(change: DeltaChange): Boolean;
  begin
    if not (change.Status = ChangeStatus.Pending) and (change.Type = ChangeType.Update) then
      exit false;
   for i: Int32 := 0 to change.Count-1 do begin
      if assigned(change.NewValues[i]) then begin
        if not change.NewValues[i].Equals(change.OldValues[i]) then
          exit false;
      end
      else begin
        // For full (ie non-reduced) Delta NewBalue[i] set to null always means that change should be applied to the database,
        // regardless of the OldValues[i] value
        if (not self.IsReduced) or assigned(change.OldValues[i]) then
          exit false;
      end;
    end;
   exit true;
  end;
begin
  var lToDelete: System.Collections.Generic.List<DeltaChange> := new System.Collections.Generic.List<DeltaChange>(self.Items.Count);
  for each change: DeltaChange in self.Items do begin
    if IsNotRealChange(change) then
      lToDelete.Add(change);
  end;
 for each change: DeltaChange in lToDelete do
    self.Items.Remove(change);
end;
  1. Rebuild the assembly and add corresponding reference to your project.

Hope this helps.
Dejan

Hi, Dejan,

Thank you! This helped me track down the problem. Since I’m working against a Delphi server, I have to use UseDynamicSelect = true and UseDynamicWhere = true in the LinqRemoteDataAdapter. The problem is caused because setting UseDynamicSelect = true was sending UseReducedDelta = true to the server, regardless of the SendReducedDelta of the data streamer (which I had set to false). Setting UseDynamicSelect to false solved the problem.

This leads me to a question to the Remobjects experts:

In this case, I’m doing a full record change, so setting UseDynamicSelect to false (and therefore, UseReducedDelta to false) helps me deal with this problem of setting string fields to null in the delta. But what if I’m only updating a few fields of a record, and some of those fields are strings that can be set to null? If I set UseDynamicSelect to true, the null strings will be deleted from the delta.

I’m using:

fDataAdapter.GetTable<Company>().UpdateRow(aCompany);
fDataAdapter.ApplyChanges();

where aCompany is a new instance with no old values. To be able to update string fields to null when using a reduced delta, do I have to keep the old object, for example, in the session, and then retrieve it on the Post action? Or is there a better way to do this not involving the session and not having to retrieve the record from the database again just to update it?

Thanks,
Arturo.

Hello

The only reliable solution here is to update the .NET assemblies used to the latest available version.

Sorry for the inconvenience.