Refactor this method to use propery name instead of field name:

procedure TMainForm.SetORMProperty(ORMRec: TQryRecInfo; const FieldName: string; const Value: TValue);
var
  Ctx: TRttiContext;
  Prop: TRttiProperty;
  ORMFieldName: string;
  ObjType: TRttiType;
begin
  Ctx := TRttiContext.Create;
  try
    ObjType := Ctx.GetType(ORMRec.ClassType);
    Prop := ObjType.GetProperty(FieldName);

    if Assigned(Prop) and Prop.IsWritable then
    begin
      ORMFieldName := '_' + FieldName;

      if ObjType.GetField(ORMFieldName) = nil then
        Exit; // Backing field not found, skip

      if Prop.PropertyType.TypeKind = tkRecord then
      begin
        // Check if the property is a TNullable<T>
        if Prop.PropertyType.Name.StartsWith('TNullable<') then
        begin
          if Value.IsEmpty or VarIsNull(Value.AsVariant) then
          begin
            // Set the property to null
            if Prop.PropertyType.Name = 'TNullable<System.string>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<string>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Integer>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Integer>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Int64>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Int64>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Extended>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Extended>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Currency>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Currency>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.TDateTime>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<TDateTime>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Boolean>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Boolean>>(NullValue))
            else if Prop.PropertyType.Name = 'TNullable<System.Variant>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Variant>>(NullValue));
          end
          else
          begin
            // Set the property with the actual value, adjust types
            if Prop.PropertyType.Name = 'TNullable<System.string>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<string>>(Value.AsString))
            else if Prop.PropertyType.Name = 'TNullable<System.Integer>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Integer>>(Value.AsInteger))
            else if Prop.PropertyType.Name = 'TNullable<System.Int64>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Int64>>(Value.AsInt64))
            else if Prop.PropertyType.Name = 'TNullable<System.Extended>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Extended>>(Value.AsExtended))
            else if Prop.PropertyType.Name = 'TNullable<System.Currency>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Currency>>(Value.AsCurrency))
            else if Prop.PropertyType.Name = 'TNullable<System.TDateTime>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<TDateTime>>(Value.AsType<TDateTime>))
            else if Prop.PropertyType.Name = 'TNullable<System.Boolean>' then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TNullable<Boolean>>(Value.AsBoolean))
            // No need to handle TNullable<Variant> since no conversion required except as fallback
            else
              raise EORMUtilsException.CreateFmt('Unsupported nullable type: %s', [Prop.PropertyType.Name]);
          end;
        end
        else
          raise EORMUtilsException.CreateFmt('Unsupported record type: %s', [Prop.PropertyType.Name]);
      end
      else
      begin
        // Handle non-nullable types
        case Prop.PropertyType.TypeKind of
          tkString, tkLString, tkWString, tkUString:
            ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsString);
          tkInteger:
            ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsInteger);
          tkInt64:
            ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsInt64);
          tkFloat:
            if Prop.PropertyType.Handle = TypeInfo(Currency) then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsCurrency)
            else if Prop.PropertyType.Handle = TypeInfo(TDateTime) then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), TValue.From<TDateTime>(Value.AsType<TDateTime>))
            else
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsExtended);
          tkEnumeration:
            if Prop.PropertyType.Handle = TypeInfo(Boolean) then
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsBoolean)
            else
              ObjType.GetField(ORMFieldName).SetValue(Pointer(ORMRec), Value.AsString);
        else
          raise EORMUtilsException.CreateFmt('Unsupported type for field "%s" in record "%s".', [FieldName, ORMRec.ClassName]);
        end;
      end;

      // After setting the ORM property, find the associated component and update it
      var Component := ORMManager.FindComponent(ORMRec, FieldName);
      if Assigned(Component) then
      begin
        ORMManager.UpdateComponentFromORM(Component, ORMRec, FieldName);
      end;

    end
    else
      raise EORMUtilsException.CreateFmt('Property "%s" not found or not writable in record "%s".', [FieldName, ORMRec.ClassName]);
  finally
    // TRttiContext is a record and managed automatically
  end;
end;