I'm working with Entity Framework 5.0 in .NET 4.5. I'm trying to build a Table Per Type (TPT) inheritance hierarchy where I have a foreign key to the primary key of one of the sub classes. Unfortunately, Entity Framework is giving me the following compile error:
Error 3024: Problem in mapping fragments starting at line 163:Must
specify mapping for all key properties (Id) of End Derived1 in
Relationship FK_Items_Derived1.
I created a test database and EF model to show demonstrate the model. My database model looks like this:
To create the Entity Framework model I:
- added these tables to the Entity Framework designer;
- selected
Base
as base type on Derived1
and Derived2
;
- removed the foreign key relationship between
Derived1
and Base
and
between Derived2
and Base
(since there's now a inheritance relationship);
- I removed the
Id
properties from Derived1
and Derived2
(since they inherit the Id
property from Base
).
This resulted is the following model:
Now when I compile it, Entity Framework prompts me with the previously stated compile error:
Error 3024: Problem in mapping fragments starting at line 163:Must
specify mapping for all key properties (Id) of End Derived1 in
Relationship FK_Items_Derived1.
The error seems to be pointing at the following line in the Model's XML mapping:
<AssociationSetMapping Name="FK_Items_Derived1"
TypeName="TestModel.FK_Items_Derived1" StoreEntitySet="Items">
<EndProperty Name="Items">
<ScalarProperty Name="Id" ColumnName="Id" />
</EndProperty>
</AssociationSetMapping>
I obviously don't want the Items
to be mapped to the Base
class, since only Derived1
has items, not Derived2
. I can't understand why the Entity Framework designer can't handle this rather common use case.
So the question of course is how to fix this?
To be complete, here's the complete Entity Framework mapping file:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="TestModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
<EntityContainer Name="TestModelStoreContainer">
<EntitySet Name="Base" EntityType="TestModel.Store.Base" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Derived1" EntityType="TestModel.Store.Derived1" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Derived2" EntityType="TestModel.Store.Derived2" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Items" EntityType="TestModel.Store.Items" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Derived1_Base" Association="TestModel.Store.FK_Derived1_Base">
<End Role="Base" EntitySet="Base" />
<End Role="Derived1" EntitySet="Derived1" />
</AssociationSet>
<AssociationSet Name="FK_Derived2_Base" Association="TestModel.Store.FK_Derived2_Base">
<End Role="Base" EntitySet="Base" />
<End Role="Derived2" EntitySet="Derived2" />
</AssociationSet>
<AssociationSet Name="FK_Items_Derived1" Association="TestModel.Store.FK_Items_Derived1">
<End Role="Derived1" EntitySet="Derived1" />
<End Role="Items" EntitySet="Items" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Base">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="uniqueidentifier" Nullable="false" />
<Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" />
</EntityType>
<EntityType Name="Derived1">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="uniqueidentifier" Nullable="false" />
<Property Name="Length" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="Derived2">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="uniqueidentifier" Nullable="false" />
<Property Name="Size" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="Items">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="uniqueidentifier" Nullable="false" />
<Property Name="Derived1Id" Type="uniqueidentifier" Nullable="false" />
<Property Name="Description" Type="nvarchar" Nullable="false" MaxLength="50" />
</EntityType>
<Association Name="FK_Derived1_Base">
<End Role="Base" Type="TestModel.Store.Base" Multiplicity="1" />
<End Role="Derived1" Type="TestModel.Store.Derived1" Multiplicity="0..1" />
<ReferentialConstraint>
<Principal Role="Base">
<PropertyRef Name="Id" />
</Principal>
<Dependent Role="Derived1">
<PropertyRef Name="Id" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Derived2_Base">
<End Role="Base" Type="TestModel.Store.Base" Multiplicity="1" />
<End Role="Derived2" Type="TestModel.Store.Derived2" Multiplicity="0..1" />
<ReferentialConstraint>
<Principal Role="Base">
<PropertyRef Name="Id" />
</Principal>
<Dependent Role="Derived2">
<PropertyRef Name="Id" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Items_Derived1">
<End Role="Derived1" Type="TestModel.Store.Derived1" Multiplicity="1" />
<End Role="Items" Type="TestModel.Store.Items" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Derived1">
<PropertyRef Name="Id" />
</Principal>
<Dependent Role="Items">
<PropertyRef Name="Derived1Id" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="TestModel" Alias="Self" p1:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:p1="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="Entities" p1:LazyLoadingEnabled="true">
<EntitySet Name="Base" EntityType="TestModel.Base" />
<EntitySet Name="Items" EntityType="TestModel.Items" />
<AssociationSet Name="FK_Items_Derived1" Association="TestModel.FK_Items_Derived1">
<End Role="Derived1" EntitySet="Base" />
<End Role="Items" EntitySet="Items" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Base">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Guid" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
</EntityType>
<EntityType Name="Derived1" BaseType="TestModel.Base">
<Property Name="Length" Type="Int32" Nullable="false" />
<NavigationProperty Name="Items" Relationship="TestModel.FK_Items_Derived1" FromRole="Derived1" ToRole="Items" />
</EntityType>
<EntityType Name="Derived2" BaseType="TestModel.Base">
<Property Name="Size" Type="Int32" Nullable="false" />
</EntityType>
<EntityType Name="Items">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Guid" Nullable="false" />
<Property Name="Description" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" />
<NavigationProperty Name="Derived1" Relationship="TestModel.FK_Items_Derived1" FromRole="Items" ToRole="Derived1" />
</EntityType>
<Association Name="FK_Items_Derived1">
<End Role="Derived1" Type="TestModel.Derived1" Multiplicity="1" />
<End Role="Items" Type="TestModel.Items" Multiplicity="*" />
</Association>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
<EntityContainerMapping StorageEntityContainer="TestModelStoreContainer" CdmEntityContainer="Entities">
<EntitySetMapping Name="Base">
<EntityTypeMapping TypeName="IsTypeOf(TestModel.Base)">
<MappingFragment StoreEntitySet="Base">
<ScalarProperty Name="Id" ColumnName="Id" />
<ScalarProperty Name="Name" ColumnName="Name" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(TestModel.Derived2)">
<MappingFragment StoreEntitySet="Derived2">
<ScalarProperty Name="Size" ColumnName="Size" />
<ScalarProperty Name="Id" ColumnName="Id" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(TestModel.Derived1)">
<MappingFragment StoreEntitySet="Derived1">
<ScalarProperty Name="Length" ColumnName="Length" />
<ScalarProperty Name="Id" ColumnName="Id" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Items">
<EntityTypeMapping TypeName="TestModel.Items">
<MappingFragment StoreEntitySet="Items">
<ScalarProperty Name="Id" ColumnName="Id" />
<ScalarProperty Name="Description" ColumnName="Description" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="FK_Items_Derived1" TypeName="TestModel.FK_Items_Derived1" StoreEntitySet="Items">
<EndProperty Name="Items">
<ScalarProperty Name="Id" ColumnName="Id" />
</EndProperty>
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
<Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</Connection>
<Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
<DesignerProperty Name="EnablePluralization" Value="False" />
<DesignerProperty Name="IncludeForeignKeysInModel" Value="False" />
<DesignerProperty Name="CodeGenerationStrategy" Value="None" />
</DesignerInfoPropertySet>
</Options>
<!-- Diagram content (shape and connector positions) -->
<Diagrams></Diagrams>
</Designer>
</edmx:Edmx>
And for anyone who wants to reproduce this locally, here are the DDL scripts:
CREATE TABLE [dbo].[Base](
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Base] PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Derived1](
[Id] [uniqueidentifier] NOT NULL,
[Length] [int] NOT NULL,
CONSTRAINT [PK_Derived1] PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Derived2](
[Id] [uniqueidentifier] NOT NULL,
[Size] [int] NOT NULL,
CONSTRAINT [PK_Derived2] PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Items](
[Id] [uniqueidentifier] NOT NULL,
[Derived1Id] [uniqueidentifier] NOT NULL,
[Description] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Items] PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Derived1] WITH CHECK ADD CONSTRAINT [FK_Derived1_Base] FOREIGN KEY([Id])
REFERENCES [dbo].[Base] ([Id])
GO
ALTER TABLE [dbo].[Derived1] CHECK CONSTRAINT [FK_Derived1_Base]
GO
ALTER TABLE [dbo].[Derived2] WITH CHECK ADD CONSTRAINT [FK_Derived2_Base] FOREIGN KEY([Id])
REFERENCES [dbo].[Base] ([Id])
GO
ALTER TABLE [dbo].[Derived2] CHECK CONSTRAINT [FK_Derived2_Base]
GO
ALTER TABLE [dbo].[Items] WITH CHECK ADD CONSTRAINT [FK_Items_Derived1] FOREIGN KEY([Derived1Id])
REFERENCES [dbo].[Derived1] ([Id])
GO
ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Derived1]
GO