danieleteti / delphimvcframework

DMVCFramework (for short) is a popular and powerful framework for WEB API in Delphi. Supports RESTful and JSON-RPC WEB APIs development.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Invalid Class Typecast" Error with Active Record and Enumerated Type

marcelojaloto opened this issue · comments

1- When you use Active Record and need to insert an enumerated field type then the error below occurs:


Debugger Exception Notification

Project Server.exe raised exception class EInvalidCast with message 'Invalid class typecast'.

The solution for this problem you need to change Ord(aValue.AsInteger) to aValue.AsOrdinal.

Unit: MVCFramework.ActiveRecord
Method: MapTValueToParam
Class: TMVCActiveRecord
Line: 2013

    tkEnumeration:
      begin
        if aValue.TypeInfo = TypeInfo(System.Boolean) then
        begin
          aParam.AsBoolean := aValue.AsBoolean;
        end
        else
        begin
          aParam.AsInteger := aValue.AsOrdinal;
        end;
      end;

2- Another error occurs when you use Active Record and you need to get an enumerated type field from the database.


Debugger Exception Notification

Project Server.exe raised exception class EInvalidCast with message 'Invalid class typecast'.

type

  TThemes = (Light, Dark);

  [MVCNameCase(ncLowerCase)]
  [MVCTable('sample')]
  TSample = class(TMVCActiveRecord)
  strict protected
    [MVCTableField('theme')]
    FTheme: TThemes;
  public
    [MVCEnumSerialization(estEnumName)]
    [MVCSwagJsonSchemaField(stEnumeration, 'theme', 'Theme', True, False, 0, 1)]
    property Theme: TThemes read FTheme write FTheme;
  end;
TSamples = class(TObjectList<TSample>)
public
  class function ReturnItem: TSample;
end;

implementation

class function TSamples.ReturnItem: TSample;
begin
  Result := TModel.GetFirstByWhere<TSample>('', [], [], False);
end;

The solution for this problem you need include a new setting when field type is a Enumeration.

Unit: MVCFramework.Serializer.Commons
Line: 1115
Method: MapDataSetFieldToRTTIField
New Lines:

        else if (aRTTIField.FieldType.TypeKind = tkEnumeration) then
        begin
          TValue(AField.AsInteger).ExtractRawData(PByte(Pointer(AObject)) + aRTTIField.Offset);
        end
procedure MapDataSetFieldToRTTIField(const AField: TField; const aRTTIField: TRttiField;
const AObject: TObject);
...
begin
  ...
  case AField.DataType of
  ...
    ftInteger, ftSmallint, ftShortint, ftByte:
      begin
        ...
        else if (aRTTIField.FieldType.TypeKind = tkEnumeration) then
        begin
          TValue(AField.AsInteger).ExtractRawData(PByte(Pointer(AObject)) + aRTTIField.Offset);
        end
      end
  ...
  end;
end;

@danieleteti Can you accept my Pull Request?

#584