I have a pretty straight forward set of database tables, like:
Vehicle
Id
RegNo
Car
Id (FK of Vehicle.Id)
OtherStuff
Bike
Id (FK of Vehicle.Id)
MoreStuff
My class model is as you'd expect: with Vehicle being an abstract class, and then Car and Bike being subclasses of it.
I have setup my EF4.1 Code First configuration as follows:
class VehicleConfiguration : EntityTypeConfiguration<Vehicle> {
public VehicleConfiguration() {
ToTable("Vehicles");
Property(x => x.Id);
Property(x => x.RegNo);
HasKey(x =&开发者_开发百科gt; x.Id);
}
}
class CarConfiguration : EntityTypeConfiguration<Car> {
public CarConfiguration() {
ToTable("Cars");
Property(x => x.OtherStuff);
}
}
class BikeConfiguration : EntityTypeConfiguration<Bike> {
public BikeConfiguration() {
ToTable("Bikes");
Property(x => x.MoreStuff);
}
}
However I am getting numerous strange exceptions when EF tried to build its model configuration.
Currently it is throwing out this:
System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.
Where is it getting that column name from? It's not in any of my code or the database itself. It must be some convention that's taking over control. How do I instruct EF to use table-per-type?
If I remove the "abstract" keyword from my Vehicle class (which I did as a sanity test somewhere along the line) then I get a different exception like the following:
(35,10) : error 3032: Problem in mapping fragments starting at lines 30, 35:EntityTypes AcmeCorp.Car, AcmeCorp.Bike are being mapped to the same rows in table Vehicles. Mapping conditions can be used to distinguish the rows that these types are mapped to.
I'm obviously doing something terribly wrong, but what? I've followed the MSDN docs and all the other TPT + EF4.1 articles I can find!
Have you read the following article?
It is a 3 part article covering the following approaches
Table per Hierarchy (TPH): Enable polymorphism by denormalizing the SQL schema, and utilize a type discriminator column that holds type information.
Table per Type (TPT): Represent "is a" (inheritance) relationships as "has a" (foreign key) relationships.
Table per Concrete class (TPC): Discard polymorphism and inheritance relationships completely from the SQL schema.
When I had this problem, I discovered that I had a subclass that was not mapped. In this example, some possible causes of this are:
- An additional subclass exists, such as
Bus
. This is not mapped. - One of the subclasses, such as
Car
, is not mapped.
In this case, ensure that every subclass is mapped:
- Ensure a mapping exists for the subclass, including a
ToTable
method call. - Ensure the mapping is actually being applied during
OnModelCreating
. - If you have trouble tracking this, try using a debugger and setting breakpoints in all of the mapping code.
Alternatively, if the subclass shouldn't be mapped in the first place, ensure that it is ignored by using one of the Ignore
method calls.
精彩评论