Using Entity Framework to map to subclassed POCO objects based on a cell in a database row
I am using Entity Framework and C# POCO objects. I have some objects that differ only in behavior; the rows of data they relate to in the DB are identical. There is a row in the database defining the class that contains the behavior.
I would really like to use an abstract class to implement the common behavior, and then instantiate subclasses from Entity Framework based of that row in the database. This example isn't what I'm working on, but I think it's analogous. If this would be the wrong way to handle a docu开发者_C百科ment, it's because it's just an analogy and I don't know anything about document management :)
For example, given these two rows from the "Document" table (with header row):
DocumentId Description DocumentType
314 A word processing document WordProcessingDocument
315 A spreadsheet SpreadsheetDocument
Ideally, I would end up with one Document.WordProcessingDocument and one Document.SpreadsheetDocument, which would have common behavior described in the abstract Document class. Entity Framework would still be managing these objects and their relationships with other objects.
Can this be done? Or can Entity Framework only instantiate one class per table? It wouldn't make sense to create a new table for each sub-type, since there would be no data in those tables. These subclasses differ in behavior only, not in their data.
This is called Table per Hiearchy (or TPH) and it is possible in EF. You must model your base class as entity and your concrete classes as entities derived from the base class. You need one special column (probably DocumentType in your example) called Discriminator which is not mapped as data but defines which sub class should be materialized when loading row from DB.
Yes, this is a standard table inheritance pattern that uses a discriminator column rather than a 1:1 relation. Create two new types in your EDMX that inherit from the current table type, then use the mapping editor to specify the column (DocumentType
) that defines which subclass to instantiate and the value that corresponds to each subclass. There's no requirement that you add any additional columns to them, but you can use partial classes to define custom business logic or behaviors for each individual type.
This also means that EF will automatically take care of assigning these values to the rows upon insert. In other words, you'll instantiate a SpreadsheetDocument
or WordProcessingDocument
and just call AddObject
. Taking this route will hide the DocumentType
column from your code entirely.
精彩评论