Фон
Я пишу библиотеку доступа к данным, используя ADO Entity Framework в Visual Studio 2008 с пакетом обновления 1 (SP1) с использованием .NET Framework 3.5 SP1. Я пытаюсь создать ассоциации между двумя сущностями, которые оба получены из абстрактного типа. Я представляю обе иерархии наследования объектов, используя Таблица для иерархии (TPH), что означает, что всего две таблицы - по одной для каждой иерархии наследования объектов.
ПРИМЕЧАНИЕ. Вы можете использовать Table Per Type (TPT), чтобы избежать этой проблемы, но она имеет свои недостатки. См. здесь и здесь для получения более подробной информации при выборе между моделями сохранения наследования.
Вот скриншот представления Designer для модели Entity:
И вот скриншот схемы базы данных:
Схема базы данных http://img7.imageshack.us/img7/8607/graphexampledatabaseschik0.th.png
Предположения
При создании ассоциаций в ADO Entity Framework Designer между производными типами, смоделированными с помощью TPH с использованием Visual Studio 2008 с пакетом обновления 1 (SP1) и .NET Framework 3.5 с пакетом обновления 1 (SP1), вы, скорее всего, получите следующее сообщение: "Ошибка 3034: отображаются два объекта с разными ключами в одну строку. Убедитесь, что эти два фрагмента отображения не отображают две группы объектов с перекрывающимися ключами в одну и ту же группу строк.
Основываясь на том, что я читал онлайн, чтобы решить эту проблему, вы должны добавить условие в ассоциацию на внешнем ключе так:
<Condition ColumnName="Endpoint1" IsNull="false" />
Вот скриншот этого редактирования для ассоциации PersonPersonToPerson1:
Ограничения
- Базовые классы каждой иерархии (т.е. Node и ссылка) должны быть абстрактными.
- Свойства навигации из ассоциаций между двумя производными типами должны быть различимы по типу ссылок (например, PersonToPerson и PersonToLocation). Это означает, что вы не можете создавать ассоциации между базовыми классами ссылок и Node.
Проблема:
Когда я создаю модель сущности, как описано выше, и добавьте условия в ассоциации, как описано в приведенных выше допущениях, я получаю "Ошибка 3023" при создании/проверке модели.
Error 1 Error 3023: Problem in Mapping Fragments starting at lines 146, 153, 159, 186, 195, 204, 213: Column Link.Endpoint1 has no default value and is not nullable. A column value is required to store entity data.
An Entity with Key (PK) will not round-trip when:
((PK is NOT in 'LinkSet' EntitySet OR PK does NOT play Role 'PersonToPerson' in AssociationSet 'PersonPersonToPerson1') AND (PK is in 'LinkSet' EntitySet OR PK plays Role 'PersonToPerson' in AssociationSet 'PersonPersonToPerson1' OR PK plays Role 'PersonToPerson' in AssociationSet 'PersonPersonToPerson'))
C:\Documents and Settings\Demo\My Documents\Visual Studio 2008\Projects\GraphExample2.BusinessEntities\GraphExample2.BusinessEntities\GraphModel.edmx 147 15 GraphExample2.BusinessEntities
То, что Entity Framework получает зависание в вышеприведенном сценарии, состоит в том, что к одним и тем же внешним ключам сопоставляются два свойства. Например, столбец и внешний ключ для конечной точки 1 сопоставляются с свойством Person в производном типе PersonToLocation и сопоставляются с его именем в свойстве Leader в производном типе PersonToPerson.
Я не понимаю, почему это проблема. Поскольку свойства Leader/Follower находятся только в производном типе PersonToPerson - не в любом другом производном или базовом типе - и то же самое относится к свойству Person/Location, почему поле TypeDiscriminator не является достаточным для того, чтобы EF мог выяснить, set заданная строка принадлежит?
Мне кажется, что если вы имеете дело с объектом, где TypeDiscriminator = 1, вы размещаете Endpoint1 в Leader и Endpoint2 в Follower. Аналогично, если вы имеете дело с объектом, где TypeDiscriminator = 2, вы размещаете Endpoint1 в Person и Endpoint2 в Location.
Вопрос:
Как вы разрешаете Ошибка 3023, чтобы разрешить эти ассоциации?
ИЛИ
Как вы создаете тип ассоциаций в ADO Entity Framework, который я описал выше?
Литература:
- Форум MSDN - Ошибка 3034: Проблема при картографии Фрагменты, начинающиеся с строк...
- Блог Zeeshan Hirani - Вклад сообщества сообщества Entity
- Zeeshan Hirani Руководство по обучению Entity Framework (это превосходное 514-страничное пошаговое руководство по многочисленным концепциям и gotchas с ADO EF ВЫСОКО рекомендуемый!)
код
SQL:
USE [GraphExample2]
GO
/****** Object: Table [dbo].[Node] Script Date: 02/17/2009 14:36:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Node](
[NodeID] [int] NOT NULL,
[NodeTypeDiscriminator] [int] NOT NULL,
[Name] [varchar](255) NOT NULL,
[Description] [varchar](1023) NULL,
CONSTRAINT [PK_Node] PRIMARY KEY CLUSTERED
(
[NodeID] 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
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[Link] Script Date: 02/17/2009 14:36:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Link](
[LinkID] [int] NOT NULL,
[LinkTypeDiscriminator] [int] NOT NULL,
[Endpoint1] [int] NOT NULL,
[Endpoint2] [int] NOT NULL,
[Name] [varchar](255) NULL,
[Description] [varchar](1023) NULL,
CONSTRAINT [PK_Link] PRIMARY KEY CLUSTERED
(
[LinkID] 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
SET ANSI_PADDING OFF
GO
/****** Object: ForeignKey [FK_Link_Node_Endpoint1] Script Date: 02/17/2009 14:36:12 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Endpoint1] FOREIGN KEY([Endpoint1])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Endpoint1]
GO
/****** Object: ForeignKey [FK_Link_Node_Endpoint2] Script Date: 02/17/2009 14:36:12 ******/
ALTER TABLE [dbo].[Link] WITH CHECK ADD CONSTRAINT [FK_Link_Node_Endpoint2] FOREIGN KEY([Endpoint2])
REFERENCES [dbo].[Node] ([NodeID])
GO
ALTER TABLE [dbo].[Link] CHECK CONSTRAINT [FK_Link_Node_Endpoint2]
GO
EDMX:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="GraphModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="GraphModelStoreContainer">
<EntitySet Name="Link" EntityType="GraphModel.Store.Link" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Node" EntityType="GraphModel.Store.Node" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Link_Node_Endpoint1" Association="GraphModel.Store.FK_Link_Node_Endpoint1">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
<AssociationSet Name="FK_Link_Node_Endpoint2" Association="GraphModel.Store.FK_Link_Node_Endpoint2">
<End Role="Node" EntitySet="Node" />
<End Role="Link" EntitySet="Link" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Link">
<Key>
<PropertyRef Name="LinkID" />
</Key>
<Property Name="LinkID" Type="int" Nullable="false" />
<Property Name="LinkTypeDiscriminator" Type="int" Nullable="false" />
<Property Name="Endpoint1" Type="int" Nullable="false" />
<Property Name="Endpoint2" Type="int" Nullable="false" />
<Property Name="Name" Type="varchar" MaxLength="255" />
<Property Name="Description" Type="varchar" MaxLength="1023" />
</EntityType>
<EntityType Name="Node">
<Key>
<PropertyRef Name="NodeID" />
</Key>
<Property Name="NodeID" Type="int" Nullable="false" />
<Property Name="NodeTypeDiscriminator" Type="int" Nullable="false" />
<Property Name="Name" Type="varchar" Nullable="false" MaxLength="255" />
<Property Name="Description" Type="varchar" MaxLength="1023" />
</EntityType>
<Association Name="FK_Link_Node_Endpoint1">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="Endpoint1" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Link_Node_Endpoint2">
<End Role="Node" Type="GraphModel.Store.Node" Multiplicity="1" />
<End Role="Link" Type="GraphModel.Store.Link" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Node">
<PropertyRef Name="NodeID" />
</Principal>
<Dependent Role="Link">
<PropertyRef Name="Endpoint2" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" Namespace="GraphModel" Alias="Self">
<EntityContainer Name="GraphModelContainer" >
<EntitySet Name="NodeSet" EntityType="GraphModel.Node" />
<EntitySet Name="LinkSet" EntityType="GraphModel.Link" />
<AssociationSet Name="PersonPersonToPerson" Association="GraphModel.PersonPersonToPerson">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToPerson" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="PersonPersonToPerson1" Association="GraphModel.PersonPersonToPerson1">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToPerson" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="Person_PersonToLocation" Association="GraphModel.Person_PersonToLocation">
<End Role="Person" EntitySet="NodeSet" />
<End Role="PersonToLocation" EntitySet="LinkSet" />
</AssociationSet>
<AssociationSet Name="Location_PersonToLocation" Association="GraphModel.Location_PersonToLocation">
<End Role="Location" EntitySet="NodeSet" />
<End Role="PersonToLocation" EntitySet="LinkSet" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Node" Abstract="true">
<Key>
<PropertyRef Name="NodeId" />
</Key>
<Property Name="NodeId" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="false" />
<Property Name="Description" Type="String" Nullable="true" />
</EntityType>
<EntityType Name="Person" BaseType="GraphModel.Node" >
<NavigationProperty Name="Leaders" Relationship="GraphModel.PersonPersonToPerson" FromRole="Person" ToRole="PersonToPerson" />
<NavigationProperty Name="Followers" Relationship="GraphModel.PersonPersonToPerson1" FromRole="Person" ToRole="PersonToPerson" />
<NavigationProperty Name="Locations" Relationship="GraphModel.Person_PersonToLocation" FromRole="Person" ToRole="PersonToLocation" />
</EntityType>
<EntityType Name="Location" BaseType="GraphModel.Node" >
<NavigationProperty Name="Visitors" Relationship="GraphModel.Location_PersonToLocation" FromRole="Location" ToRole="PersonToLocation" />
</EntityType>
<EntityType Name="Link" Abstract="true">
<Key>
<PropertyRef Name="LinkId" />
</Key>
<Property Name="LinkId" Type="Int32" Nullable="false" />
<Property Name="Name" Type="String" Nullable="true" />
<Property Name="Description" Type="String" Nullable="true" />
</EntityType>
<EntityType Name="PersonToPerson" BaseType="GraphModel.Link" >
<NavigationProperty Name="Leader" Relationship="GraphModel.PersonPersonToPerson" FromRole="PersonToPerson" ToRole="Person" />
<NavigationProperty Name="Follower" Relationship="GraphModel.PersonPersonToPerson1" FromRole="PersonToPerson" ToRole="Person" />
</EntityType>
<EntityType Name="PersonToLocation" BaseType="GraphModel.Link" >
<NavigationProperty Name="Person" Relationship="GraphModel.Person_PersonToLocation" FromRole="PersonToLocation" ToRole="Person" />
<NavigationProperty Name="Location" Relationship="GraphModel.Location_PersonToLocation" FromRole="PersonToLocation" ToRole="Location" />
</EntityType>
<Association Name="PersonPersonToPerson">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToPerson" Role="PersonToPerson" Multiplicity="*" />
</Association>
<Association Name="PersonPersonToPerson1">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToPerson" Role="PersonToPerson" Multiplicity="*" />
</Association>
<Association Name="Person_PersonToLocation">
<End Type="GraphModel.Person" Role="Person" Multiplicity="1" />
<End Type="GraphModel.PersonToLocation" Role="PersonToLocation" Multiplicity="*" />
</Association>
<Association Name="Location_PersonToLocation">
<End Type="GraphModel.Location" Role="Location" Multiplicity="1" />
<End Type="GraphModel.PersonToLocation" Role="PersonToLocation" Multiplicity="*" />
</Association>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS" Space="C-S">
<Alias Key="Model" Value="GraphModel" />
<Alias Key="Target" Value="GraphModel.Store" />
<EntityContainerMapping CdmEntityContainer="GraphModelContainer" StorageEntityContainer="GraphModelStoreContainer">
<EntitySetMapping Name="LinkSet">
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Link)">
<MappingFragment StoreEntitySet="Link">
<ScalarProperty Name="Description" ColumnName="Description" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.PersonToPerson)">
<MappingFragment StoreEntitySet="Link" >
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
<Condition ColumnName="LinkTypeDiscriminator" Value="1" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.PersonToLocation)">
<MappingFragment StoreEntitySet="Link" >
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
<Condition ColumnName="LinkTypeDiscriminator" Value="2" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="NodeSet">
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Node)">
<MappingFragment StoreEntitySet="Node">
<ScalarProperty Name="Description" ColumnName="Description" />
<ScalarProperty Name="Name" ColumnName="Name" />
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Person)">
<MappingFragment StoreEntitySet="Node" >
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
<Condition ColumnName="NodeTypeDiscriminator" Value="1" />
</MappingFragment>
</EntityTypeMapping>
<EntityTypeMapping TypeName="IsTypeOf(GraphModel.Location)">
<MappingFragment StoreEntitySet="Node" >
<ScalarProperty Name="NodeId" ColumnName="NodeID" />
<Condition ColumnName="NodeTypeDiscriminator" Value="2" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<AssociationSetMapping Name="PersonPersonToPerson1" TypeName="GraphModel.PersonPersonToPerson1" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="Endpoint1" />
</EndProperty>
<EndProperty Name="PersonToPerson">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
<Condition ColumnName="Endpoint1" IsNull="false" />
</AssociationSetMapping>
<AssociationSetMapping Name="PersonPersonToPerson" TypeName="GraphModel.PersonPersonToPerson" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="Endpoint2" />
</EndProperty>
<EndProperty Name="PersonToPerson">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
<Condition ColumnName="Endpoint2" IsNull="false" />
</AssociationSetMapping>
<AssociationSetMapping Name="Person_PersonToLocation" TypeName="GraphModel.Person_PersonToLocation" StoreEntitySet="Link">
<EndProperty Name="Person">
<ScalarProperty Name="NodeId" ColumnName="Endpoint1" />
</EndProperty>
<EndProperty Name="PersonToLocation">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
<Condition ColumnName="Endpoint1" IsNull="false" />
</AssociationSetMapping>
<AssociationSetMapping Name="Location_PersonToLocation" TypeName="GraphModel.Location_PersonToLocation" StoreEntitySet="Link">
<EndProperty Name="Location">
<ScalarProperty Name="NodeId" ColumnName="Endpoint2" />
</EndProperty>
<EndProperty Name="PersonToLocation">
<ScalarProperty Name="LinkId" ColumnName="LinkID" />
</EndProperty>
<Condition ColumnName="Endpoint2" IsNull="false" />
</AssociationSetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</edmx:Connection>
<edmx:Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
</DesignerInfoPropertySet>
</edmx:Options>
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram Name="GraphModel" ZoomLevel="114" >
<EntityTypeShape EntityType="GraphModel.Node" Width="1.5" PointX="5.875" PointY="1.375" Height="1.427958984375" />
<EntityTypeShape EntityType="GraphModel.Person" Width="1.5" PointX="5.875" PointY="3.25" Height="1.4279589843749996" />
<EntityTypeShape EntityType="GraphModel.Location" Width="1.5" PointX="7.75" PointY="4.625" Height="1.0992643229166665" />
<InheritanceConnector EntityType="GraphModel.Location">
<ConnectorPoint PointX="7.375" PointY="2.0889794921875" />
<ConnectorPoint PointX="8.5" PointY="2.0889794921875" />
<ConnectorPoint PointX="8.5" PointY="4.625" />
</InheritanceConnector>
<EntityTypeShape EntityType="GraphModel.Link" Width="1.5" PointX="2.875" PointY="1.375" Height="1.427958984375" />
<EntityTypeShape EntityType="GraphModel.PersonToPerson" Width="1.75" PointX="2.625" PointY="3.125" Height="0.9349169921875" />
<InheritanceConnector EntityType="GraphModel.PersonToPerson">
<ConnectorPoint PointX="3.625" PointY="2.802958984375" />
<ConnectorPoint PointX="3.625" PointY="3.125" />
</InheritanceConnector>
<InheritanceConnector EntityType="GraphModel.Person">
<ConnectorPoint PointX="6.625" PointY="2.802958984375" />
<ConnectorPoint PointX="6.625" PointY="3.25" />
</InheritanceConnector>
<EntityTypeShape EntityType="GraphModel.PersonToLocation" Width="1.875" PointX="0.75" PointY="4.625" Height="1.2636116536458326" />
<InheritanceConnector EntityType="GraphModel.PersonToLocation">
<ConnectorPoint PointX="2.875" PointY="2.0889794921875" />
<ConnectorPoint PointX="1.65625" PointY="2.0889794921875" />
<ConnectorPoint PointX="1.65625" PointY="4.625" />
</InheritanceConnector>
<AssociationConnector Association="GraphModel.PersonPersonToPerson">
<ConnectorPoint PointX="5.875" PointY="3.8193058268229163" />
<ConnectorPoint PointX="4.375" PointY="3.8193058268229163" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.PersonPersonToPerson1">
<ConnectorPoint PointX="5.875" PointY="3.4721529134114579" />
<ConnectorPoint PointX="4.375" PointY="3.4721529134114579" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.Person_PersonToLocation">
<ConnectorPoint PointX="6.625" PointY="4.677958984375" />
<ConnectorPoint PointX="6.625" PointY="5.1875" />
<ConnectorPoint PointX="2.625" PointY="5.1875" />
</AssociationConnector>
<AssociationConnector Association="GraphModel.Location_PersonToLocation">
<ConnectorPoint PointX="7.75" PointY="5.4791666666666661" />
<ConnectorPoint PointX="2.625" PointY="5.4791666666666661" />
</AssociationConnector>
</Diagram>
</edmx:Diagrams>
</edmx:Designer>
</edmx:Edmx>