Skip to content

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

@marcelojaloto

Description

@marcelojaloto

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;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions