Abstract base class without DB table mapping in Entity Framework

abstract-class c# entity-framework


I have a situation where I have 4-5 very similar classes which I'd like to re-factor to use an abstract base class. The idea behind this would be allow methods which could be used by each class whilst adhering to DRY principles.

The problem I have is that these classes are Entity classes generted from EF4 and each time I try to alter my model it seems to break down.

What's the best/recommended, method to add a base class into my EF model and make the existing classes in the model inherit from this as a base? At the moment I've got no problem adding the base class, giving it an ID property as it seems to require, and then creating the inheritence, but EF then moans about

'Error 3024: Problem in mapping fragments starting at line 18563:Must specify mapping for all key properties (MyBaseType.ID) of the EntitySet MyBaseType.'

In this situation I don't want the base type to be persisted to the DB, purely used as a container for base methods common to all the classes which inherit from it. It feels like I'm missing something simple here but I can't for the life of me see it.

Any ideas on how to add in a base class in this way? Or should I just be adding the base class in code and bypassing the model somehow?

EDIT: As further information, take an example where there are say 3 types, MortageApplicationForm, BankAccountApplicationForm and CreditCardApplication form. They are currently stored in 3 different tables, with a set of different fields. What I'm trying to do, is create a base class of say 'Form' which will have the common fields in it.

At a simple level, say that each table has a primary key ID field called, 'CreditCardFormID', 'BankAccountFormID' etc What I'd like to do it create a base 'Form' class with a property 'ID' which for the case of one table will map to 'CreditCardFormID' and another 'BankAccountFormID'.

I'm happy to do this mapping in partial classes (as I don't want to persist 'ID' to the DB) I simply want to use it in code, so I can write generic methods for things like LoadForm(int ID) without needing to write huge switches for each entity type, or specific methods for each entity type.

11/7/2011 5:15:22 PM

Accepted Answer

I managed to find a work around for this by rejigging things slightly. Firstly, I did not have the time available to rework the model (which I think would have been the best solution) too much of the system has already been developed with the existing structure to rip it all apart at this point.

The solution so far, has been to create a static helper class to contain business logic which is generic accross in my example, the 3 different account types.

This was coupled with an 'IAccount' interface, allowing the helper class to take an IAccount instance as a parameter (allowing the passing of any particular account type.) This interface contained all the common properties accross the 3-4 concrete classes. It was important to note that in order to create generic methods which I could call on all the classes I was not able to use any other properties specific to the class.

Within the helper methods, I needed to switch my concrete XYZEntities instance to a more generic 'ObjectContext' object and then use the methods such as 'AddObject' rather than 'AddBankAccountForm', 'AddCreditCardForm' etc explicitely. This involved a tiny bit of GetType()'ing to ensure the object was passed to the correct ObjectSet, but seems to work as desired.

11/24/2011 8:52:17 AM

Popular Answer

There are 3 patterns for this:

  • Table per Class Hierarchy. All concrete types in the inheritance heirarchy are stored in one table.
  • Table per Type. Each type in the inheritance is stored in it's own table.
  • Table per Concrete class. A table for each concrete class but no table for the abstract class.

In your case with the existing tables the Table per Concrete class looks like the best fit.

There is a good description of these options in this book

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow