Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attribute mapping #6

Closed
GoogleCodeExporter opened this issue Mar 20, 2015 · 5 comments
Closed

Attribute mapping #6

GoogleCodeExporter opened this issue Mar 20, 2015 · 5 comments

Comments

@GoogleCodeExporter
Copy link
Collaborator

Support for mapping classes using attributes instead of an external json 
mapping.

Maybe there will be situations where a mapping is dificult/impossible to 
express via attributes, but for these cases the programmer can always use the 
standard json mapping. As for the most cases, I think a good set of attributes 
will do the job much better than the json mapping.

For exemple, this class:

type
  TCustomer = class
  private
    FId: Integer;
    FName: String;
    FAge: Integer;
  public
    property Id: Integer read FId write FId;
    property Name: String read FName write FName;
    property Age: Integer read FAge write FAge;
  end;

Could be mapped this way:
type
  [Table('CUSTOMER')]
  TCustomer = class
  private
    [PrimaryKey]
    [Column('ID')]
    FId: Integer;
    [Column('NAME')]
    FName: String;
    [Column('AGE')]
    FAge: Integer;
  public
    property Id: Integer read FId write FId;
    property Name: String read FName write FName;
    property Age: Integer read FAge write FAge;
  end;

And if http://code.google.com/p/delphi-orm/issues/detail?id=5 got implemented, 
the class with it's complete mapping would be reduced to:
type
  TCustomer = class
  private
    [PrimaryKey]
    FId: Integer;
    FName: String;
    FAge: Integer;
  public
    property Id: Integer read FId write FId;
    property Name: String read FName write FName;
    property Age: Integer read FAge write FAge;
  end;

Original issue reported on code.google.com by magn...@gmail.com on 17 Nov 2011 at 6:58

@GoogleCodeExporter
Copy link
Collaborator Author

If you have interest on put this on the project, I could contribute with some 
work

Original comment by magn...@gmail.com on 18 Nov 2011 at 1:24

@GoogleCodeExporter
Copy link
Collaborator Author

I have interest too, and i know magno. we can work together on this part!

Original comment by mrbar2000@gmail.com on 18 Nov 2011 at 1:28

@GoogleCodeExporter
Copy link
Collaborator Author

[deleted comment]

@GoogleCodeExporter
Copy link
Collaborator Author

If someone were to implement this feature, I was thinking of this:

type
  Table = class(TCustomAttribute)
  private
    FTableName: String;
  public
    constructor Create(const TableName: String);
    property TableName: String read FTableName;
  end;
  IMappingStrategy = interface
    // guid
    function GetTableName(const AType: TRttiType): String;
  end;

  TCoCMappingStrategy = class(TInterfacedObject, IMappingStrategy)
    { Return the classname on uppercase and without the 'T' prefix }
    function GetTableName(const AType: TRttiType): String;
  end;

  TAttributeMappingStrategy = class(TInterfacedObject, IMappingStrategy)
    { If the class has a 'Table' attribute, returns it's 'TableName' property.
      Return empty string otherwise }
    function GetTableName(const AType: TRttiType): String;
  end;

  TExternalMappingStrategy = class(TInterfacedObject, IMappingStrategy)
    { Read from the external mapping file, as DORM does today }
    function GetTableName(const AType: TRttiType): String;
  end;

  TDelegateMappingStrategy = class(TInterfacedObject, IMappingStrategy)
    { An array of the strategies that can be used by the app to solve a given mapping. }
    FStrategies: TArray<IMappingStrategy>;
    constructor Create(const Strategies: array of IMappingStrategy);
    { This will iterate over FStrategies and try all of them to resolve the table name.
      The first one that returns something will be used.
      So, the array FStrategies must contain, in this order:
      TExternalMappingStrategy
      TAttributeMappingStrategy
      TCocMappingStrategy

      So: The attributes mapping will be used only if the mapping we're looking for doesn't exist on the external file. And the CoC mapping will be used only if the mapping we're looking for doesn't exist on both the external file and on the attributes }
    function GetTableName(const AType: TRttiType): String;
  end;

At TSession creation, maybe the programmer could even supply an 
IMappingStrategy of his own, this could be useful e.g.:
1. To customize the conventions. Maybe the programmer wants TCustomer to be 
mapped to TBL_CUSTOMER instead of CUSTOMER
2. To reuse existing mapping code that were used on other framework. The 
programmer may be moving from another ORM to DORM, and want DORM to use all the 
existing mapping code

Another advantage of this approach is that it completely separate mapping 
resolution code from the framework core, allowing all the mapping strategies to 
be very easily unit tested.

After all, it will also solve Issue 5 :)

Original comment by magn...@gmail.com on 18 Nov 2011 at 10:23

@GoogleCodeExporter
Copy link
Collaborator Author

The new ideas for mapping are very good guys. Thanks for this suggestions. 
However, I'm currently focusing on the CORE engine of dorm to do some 
optimization and enhance the functionalities. So, if you are available to 
contribute to dorm, I'd very happy. If you (magnomp and  mrbar2000) are 
interested to become controbutors, drop me an email with your google account.
We have to identify a good way to do database generation when attribute or CoC 
mapping is used. Currently, the dormDatabaseCreator, use the mapping file to 
create the database.

Original comment by daniele....@gmail.com on 22 Nov 2011 at 5:03

  • Changed state: Accepted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant