invalid coding using TBlob with TDbWideMemo Part 2

reopening: invalid coding using TBlob with TDbWideMemo

This error only occurs using Controls with Windows RichEdit library.

My fix needs to override SetPropValue of TAureliusDataset.

if not TrySetBlobRtf(aPropName, Obj, Value, procedure(aBlob: TBlob; aOpti: TRttiOptimization)
      begin
        Explorer.SetMemberValue(Obj, aOpti, TValue.From(aBlob));
      end) then
      inherited;
function TrySetBlobRtf(aPropName: string; aObj: TObject; aValue: ValueType; aOnSetValue: TProc<TBlob, TRttiOptimization>): Boolean;
var
  hOpti: TRttiOptimization;
  hMember: TRttiMember;
  hBlob: TBlob;
begin
  Result := False;

  if VarIsNull(aValue) or VarIsEmpty(aValue) or not VarIsStr(aValue) then
    Exit;

  hOpti := Explorer.FindOptimization(aObj.ClassType, aPropName);
  try
    hMember := nil;
    if Assigned(hOpti) then
      hMember := hOpti.MemberRef;

    if Assigned(hMember) and hMember.HasAttribute<DbTypeWideMemo> then
    begin
      hBlob.AsUnicodeString := Trim(VarToStr(aValue)); // VarToStr returns  #13#10#0 instead of #13#10 from VarToStrDef... so we have to trim...
      aOnSetValue(hBlob, hOpti);
      Result := True;
    end;
  finally
    hOpti.Free;
  end;
end;

I'm not sure if this a question or a clarification post. I also don't see what you changed in SetPropValue.

Can you please provide the description of the problem and a project/steps to reproduce the issue, if there is any?

it should have clarified stuff, but looks like it failed...

in TCustomAureliusDataset.SetPropValue you are doing this:

  if SubProp = '' then
  begin
    if O.RealType.IsInstance then
      MemberValue := TValue.From<TObject>(VariantToObject(Value))
    else
    begin
      if (O.IsNullable or O.IsAssignable) and VarIsNull(Value) then
        MemberValue := TValue.Empty
      else
      if IsEnumeration(O.RealType.Handle) then
        MemberValue := TValue.FromOrdinal(O.RealType.Handle, Value)
      else
        MemberValue := Explorer.VariantToValue(Value, O); // got trailing #0 in MemberValue
    end;
    Explorer.SetMemberValue(Obj, O, MemberValue);
  end
...

taking a look into TMappingExplorer.VariantToValue:

...
  if IsBlob(ATypInfo) then
  begin
    if VarIsNull(Value) or VarIsEmpty(Value) then
      blob.IsNull := True
    else
      blob.AsBytes := TUtils.VariantToBytes(Value); // recieving TBytes with leading #0
    Result := TValue.From<TBlob>(blob);
  end
...

that's because string(V) is returning this wrong value in TUtils.VariantToBytes is returning

...
varUString: result := TEncoding.Unicode.GetBytes(string(V));
...

You would need a blob field in your entity with DbTypeWideMemo.
Open this in TAureliusDataset and
set fieldvalue using AsVariant := 'sometext' + #13#10#0;
You will see, that #0 will also appear in Bytestream...

hopefully this would clarify my issue...

That code is there for years. The TEncoding.GetBytes is simply that, get the bytes of a string.

If you are using this with something that is not exactly a string - but a RTF - you should not use ftWideMemo or [DBTypeWideMemo], but instead just using a raw TBlob type.