Vertical Inheritance and the discriminator column - Using Code only
I am trying to map a vertical inheritance between a base class and derived class (obviously). I am using code-only and the FluentAPI approach for which I have found very little documentation. I have found a couple of docs on vertical inheritance and code-only but very few on managing the discriminator column/value.
So I have been trying to extrapolate how to do it from a combination of this blog post and some documentation on implementing vertical inheritance using code-only. All to no avail.
I am also providing a link to my DB Diagram (easier than typing in all that code and easier to read).
You will see that I have a "Deliverables" base table and "PrintDeliverables" derives from that. There will be other "Deliverable" derivatives coming down the road. But I figured I would start with one first.
Anyway, I naturally have models that map to the tables.
01.
public
class
PrintDeliverable : BDeliverableBase
02.
{
03.
public
String PaperItemNumber {
get
;
set
; }
04.
05.
public
String PrinterModel {
get
;
set
; }
06.
07.
public
Boolean? ColorOption {
get
;
set
; }
08.
09.
public
String ProductCode {
get
;
set
; }
10.
11.
}
12.
13.
public
class
BDeliverableBase : BModelBase, IDeliverable, ISingleID
14.
{
15.
public
Int64 ID {
get
;
set
; }
16.
17.
public
String Label {
get
;
set
; }
18.
19.
public
String Description {
get
;
set
; }
20.
21.
public
IList<DeliverableAttribute> Attributes {
get
;
set
; }
22.
23.
public
Int64 TypeID {
get
;
set
; }
24.
public
DeliverableType Type {
get
;
set
; }
25.
26.
}
27.
28.
public
class
DeliverableType : BModelBase, ISingleID
29.
{
30.
31.
public
Int64 ID {
get
;
set
; }
32.
33.
public
String Label {
get
;
set
; }
34.
35.
public
String Description {
get
;
set
; }
36.
37.
public
IList<BDeliverableBase> Deliverables {
get
;
set
; }
38.
}
I have the standard mapping which maps the fields and types, sizes, etc. When I run it with no further additions I get an Error "Invalid Column name voa_class". My research uncovered that the ORM is attempting to update a "discriminator" column with a value that will tie the base table and associated table with the derived data together. So I learned that I can change the name of the column it uses which I did, in the BASE CLASS mapping (BDeliverableBase). I changed it to use the "DeliverableTypeId" column. Since the DeliverableType indicates which TYPE of deliverable it is, each type will have a separate associated table to keep it's type-specific information in, but derived from the Deliverables table.
MappingConfiguration<BDeliverableBase> map =
new
MappingConfiguration<BDeliverableBase>();
map.HasDiscriminator().ToColumn(
"DeliverableTypeId"
);
It appears to like this better but it wants to insert this crazy number (ex// 612274703-854) into the "DeliverableTypeId" column which, of course, being a foreign key to the DeliverableTypes table is not allowed.
Insert of '612274703-' failed: Telerik.OpenAccess.RT.sql.SQLException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_DeliverableType". The conflict occurred in database "DB1", table "dbo.DeliverableTypes", column 'DeliverableTypeId'
I continued my research to learn that OpenAccess/DataAccess generates a hash value to insert into the discriminator column. I do not want this, in fact I know that the value will must one of the ID values available in the DeliverableType. So I read in one of the docs that you could also define what value to assign to the discriminator. The example applied a hard-coded value to the base class (dog and cat derived from animal) ...
animal.HasDiscriminatorValue(
"23"
);
This presented one problem ... I do not have a single value I can hard-code. It could one of MANY values present in the DeliverableType table. However, for the sake of proving out the concept I hard-coded the value of an existing record in the base class mapping.
MappingConfiguration<BDeliverableBase> map =
new
MappingConfiguration<BDeliverableBase>();
map.HasDiscriminator().ToColumn(
"DeliverableTypeId"
);
map.HasDiscriminatorValue(
"819"
);
I continued to get the identical error as before. So it doesn't appear that it was applying my hard-coded value. So ... I thought, while hard-coding the value is a little hacky it would make more sense to define that value in the mapping for the derived class. That would resolve my hard-coded issue since ALL instances of that derived class WOULD indeed be of the same DeliverableTypeId. So I tried ...
MappingConfiguration<BDeliverableBase> map =
new
MappingConfiguration<BDeliverableBase>();
map.HasDiscriminator().ToColumn(
"DeliverableTypeId"
);
MappingConfiguration<PrintDeliverable> map =
new
MappingConfiguration<PrintDeliverable>();
map.HasDiscriminatorValue(
"819"
);
This resulted in the Error
Insert of '612274703-857' failed: Telerik.OpenAccess.RT.sql.SQLException: String or binary data would be truncated.
So I got a different error but still the same poblem. This time it was trying to stuff the ORM generated discriminator value (instead of my 819) into what I am assuming is my defined discriminator column (DeliverableTypeId). The different error makes me suspicious that it was targeting a different column.
In an effort to not drag this out too long, suffice to say I have tried several combinations of where to these "HasDiscriminator" and "HasDiscriminatorValue" assignments go but always end up with one or the other of these errors. So the question is ...
How, using code-only, do I map Vertical Inheritance using multiple, existing "type" values?
Thanks in advance!