I was wondering if anyone had any experience implementing inheritances in reverse mapped database. I saw this post, but is very out of date and seems to no longer be applicable. I have a database with 50 or so tables and most, if not all of them, inherit properties from a base class. It would be nice to translate this into the ORM Model somehow.
Any timely help will be greatly appreciated.
Thanks,
Jay
7 Answers, 1 is accepted
The article you mentioned is actually refers to the "classic" wizards of OpenAccess. As we do not have such article about the visual designer, I will give you some directions how to achieve that.
Consider the following scenario:
1. We will use the Person and Employee tables described in the post you saw. The only change we need to do is to modify Employee's primary key column name from "EmployeeID" to "PersonID". The primary key columns of the two tables need to be with the same name.
2. A new domain model should be generated from the database. This can be done by right-clicking on the project, selecting OpenAccess>Add domain model and following the wizard steps.
3. After the domain model is generated, some modifications have to be done. First of all, remove the relations between the classes (right-click on the connection and click Delete).
4. Then remove the PersonID property from the Employee class, as it will inherit the identity of the Person base class.
5. Add inheritance relationship between the two classes so that Employee inherits from Person. This can be done by clicking on the Toolbox button (this will open the toolbox), selecting the "Inheritance" connection and dragging it from Employee to Person.
6. As the two classes are mapped to separate tables, Vertical inheritance will have to be used. To set it, select the Employee class and at the bottom of Visual Studio select the Mapping Details Editor tab. Then set the Inheritance strategy to Vertical.
7. Open the Discriminator combo box located in the Mapping Details Editor and select <NONE>, you should do this even if it's already selected. This is a small visual bug we are working on.
8. Finally, check if the classes are mapped to the tables . The Employee mapping will probably be gone, so it has to be added again.
Now everything should be ready. You can test it by using few simple lines of code, for example :
EntitiesModel model =
new
EntitiesModel();
Employee emp =
new
Employee();
// assign values to members
model.Add(emp);
model.SaveChanges();
The appropriate record should be added to the database.
(Note that for Vertical mapping, the Discriminator column is not mandatory, more information on the different kinds of mapping can be found here. )
If you want to use a discriminator column, you have two options :
1. Create it manually in the initial table and then select it from the Mapping Details Editor.
2. Create the discriminator column manually in the Model Schema Explorer (Tables>Person>Add new column)
and then in the Mapping Details Editor select it to be a Discriminator. Check if the mapping is correct. Right-click on the rlinq designer and click Update database from model. The discriminator column will be generated in the Person table, along with any other modifications.
I hope this helps. If you need further assistance, do not hesitate to ask.
Best Regards
Kosta
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
(Database: MySql)
If your "children database tables" primary key fields originally where set to AUTOINC, you will need to
remove these statements in the database-diagram-name.rlinq.diagram
<
orm:identity
>
<
orm:key-generator
name
=
"autoinc"
/>
</
orm:identity
>
(Not sure what happens if they where never set to AUTOINC)
They are not removed when updating these tables from the database setting AUTOINC to false, and they cause this runtime exception:
Telerik.OpenAccess.OpenAccessException: The db-key-generator extension is only allowed for the least derived class in a hierarchy
Gunnar
Thanks for making this note. As an alternative to changing the XML, you can take the same action in the UI via the Visual Designer. You should just select the derived entity and set the Identity mechanism property from DatabaseServerCalculated to Default. This will cause OpenAccess to internally calculate the correct value for the identity property of your objects e.g. to take the value from the base class.
All the best,
Kosta
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
Reverted back to having Telerik ORM create the primary keys:
Doing just the above instructions I get:
Invalid object name 'voa_keygen'. Telerik.OpenAccess.RT.sql.SQLException: Invalid object name 'voa_keygen'.
at Telerik.OpenAccess.RT.Adonet2Generic.Impl.StatementImp.executeQuery(String sql)
at OpenAccessRuntime.Relational.sql.HighLowRelationalKeyGenerator.IsCached(Connection con, RelationalKeyGeneratorInfoCache infoCache, String tab, String kCol, String vCol, String key, Boolean& ret)
at OpenAccessRuntime.Relational.sql.HighLowRelationalKeyGenerator.init(String className, RelationalTable theClassTable, Connection con, RelationalKeyGeneratorInfoCache relationalKeyGeneratorInfoCache)
at OpenAccessRuntime.Relational.RelationalStorageManagerFactory.init(Boolean full)
Cannot get the "Update Database from Model" (tried both MySql and MSSQL 2008) to generate the voa_keygen table.
Also it seems from Exceptions I get that the Mother table is expected to have a voa_class field...
I do get around this by adding the neccessary table voa_keygen and the field voa_class to all mother tables.
However, my database script should ideally be kept clean of proprietary ORM stuff, so I would very much prefer this to work from Telerik.OpenAccess (having an extra db script is also kind of messy).
Thanks
Gunnar
Please, let me apologize for the little misunderstanding I believe we caused with the posts in this discussion. Here are a few words on vertical inheritance so you can understand the situation better:
- In vertical inheritance, the primary key is always obtained from the 'Parent' table.
- The above means that the child table should not have any identity mechanism set. That is why disabling autoinc in the designer is propose in one of the previous posts. However this should be done only in cases where OpenAccess will create your database schema.
- If you have AUTOINC identity mechanism on the child table in your database, you will not be able to setup a valid vertical inheritance where this table is mapped to the inheritor in the relationship. One of the workarounds is to make the class mapped to this table the parent or base class in the relationship if your business logic allows it.
Zoran
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>
First of all, as stated in my post above, I removed the AUTOINC from all tables in the database.
I am aware about the vertial inheritance parent and child tables, however, we do have a primary key in the child tables as well which is also a foreign key to the parent table (we have as a principle that all tables must have a primary key).
As I understand this might be what trips up the voa_class and keygen generation from OpenAccess inn this case - will test this when I get the time and have talked to the db designer.
Thanks
Gunnar
Zoran
the Telerik team
Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's SQL Server Community Awards. We are competing in TWO categories and every vote counts! VOTE for Telerik NOW >>