3

I have a model hierarchy configuration like so:

[Table("A")]
abstract class A { }

class B : A { } // treated as abstract

[Table("C")]
class C : B { }

This results in a TPH for A and B, and a TPT for C. So far this seems to work fine. There are two database tables being generated: "A" which contains both A and B model records, and "C" which contains only C model record columns not already kept in table "A".

For the TPH arrangement on Table A, there is a generated "Discriminator" column, which EF CF creates on its own to distinguish type A vs type B. This column is fine and expected; however, I would like to rename it. For this post's sake, the new name might be "Type".

The tutorials that document how to do this appear to suggest this:

modelBuilder.Entity<A>()
   .Map<B>(m=>m.Requires("Type").HasValue(typeof(B).Name))
   .Map<C>(m=>m.Requires("Type").HasValue(typeof(C).Name));

This does not seem to work, though, as I get a runtime error during database generation saying that the models of types A, B, and C are being added to the same table, and, "Mapping conditions can be used to distinguish the rows that these types are mapped to." (Whatever this means.)

I also tried:

modelBuilder.Entity<A>()
    .Map<B>(m=>m.Requires("Type"))
    .Map<C>(m=>m.Requires("Type"));

.. as well as ..

modelBuilder.Entity<A>().Map(m=>m.Requires("Type"));

.. and even though these attempts compile and produce no runtime errors, there seems to be no effect, as the Discriminator column remains as "Discriminator".

I tried to create a new string property on A called "Discriminator", to which I was going to subsequently rename the property's column metadata, but that just gave me two "Discriminator" columns: "Discriminator" and "Discriminator1".

Ideas?

Jon Davis
  • 6,562
  • 5
  • 43
  • 60

2 Answers2

1

Not strictly an answer but just confirmation that the approach should work...

I have just managed to rename the discriminator field in a TPH structure we're using. The hierarchy has an enum value to distinguish types.
A is the base class, B is a slightly more refined version, C,D and E are the concrete classes.

class A
class B : A
class C : B
class D : B
class E : A

modelBuilder.Entity<A>()
            .Map<B>(m => m.Requires("TypeId").HasValue((int)MyType.ClassB))
            .Map<C>(m => m.Requires("TypeId").HasValue((int)MyType.ClassC))
            .Map<D>(m => m.Requires("TypeId").HasValue((int)MyType.ClassD))
            .Map<E>(m => m.Requires("TypeId").HasValue((int)MyType.ClassE));

I had to remember to include every derived class type even if it was never used as a concrete class. Originally I forgot to include B as I was thinking it was not required and the discriminator field would keep appearing.

I can imagine EF getting a little confused if you try to map your C class even though it is in a different table.

The error message you mention in your comment sounds like some of the HasValue requirements are producing the same value for different class types - perhaps.

Edit:
Just read this which seems to deal with the same error message.

shunty
  • 3,699
  • 1
  • 22
  • 27
0

You cannot map discriminator for C because it is not part of your TPH hierarchy. Try just this:

modelBuilder.Entity<A>()
            .Map<B>(m=>m.Requires("Type").HasValue(typeof(B).Name));
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Trying what you shared for both of two B entities (and excluding C in said .Map()'ing) results in the same thing: "(36,10) : error 3032: Problem in mapping fragments starting at lines 28, 36:EntityTypes B, B2, C are being mapped to the same rows in table A. Mapping conditions can be used to distinguish the rows that these types are mapped to." – Jon Davis Jul 11 '11 at 09:14
  • Well, I played with this whole evening and this is quite challenging - I got very close with two mappings but it produced other error at the end. Btw. your C is not mapped with TPC but with TPT inheritance and you should probably consider not combining these inheritance types together - especially if you mentioned that B is like abstract entity. – Ladislav Mrnka Jul 11 '11 at 22:15