简体   繁体   中英

What is the proper way to create a recursive entity in the Entity Framework?

I'm currently using VS 2010 RC, and I'm trying to create a model that contains a recursive self-referencing entity. Currently when I import the entity from the model I get an error indicating that the parent property cannot be part of the association because it's set to 'Computed' or 'Identity', though I'm not sure why it does it that way. I've been hand-editing the file to get around that error, but then the model simply doesn't work.

What is the proper way to get recursive entities to work in the Entity Framework.

The model imported by default doesn't work. I've tried several adjustments and end up getting a different type of error each time. At this point I'm looking for a solution and an explanation as to why the solution is correct.

Relevant Database Object

CREATE TABLE [dbo].[Appointments](
    [AppointmentId] [int] IDENTITY(1,1) NOT NULL,
    [Description] [nvarchar](1024) NULL,
    [Start] [datetime] NOT NULL,
    [End] [datetime] NOT NULL,
    [Username] [varchar](50) NOT NULL,
    [RecurrenceRule] [nvarchar](1024) NULL,
    [RecurrenceState] [varchar](20) NULL,
    [RecurrenceParentId] [int] NULL,
    [Annotations] [nvarchar](50) NULL,
    [Application] [nvarchar](100) NOT NULL,
    CONSTRAINT [PK_Appointments] PRIMARY KEY CLUSTERED 
    (
        [AppointmentId] ASC
    )
)
GO

ALTER TABLE [dbo].[Appointments]  WITH CHECK ADD  CONSTRAINT [FK_Appointments_ParentAppointments] FOREIGN KEY([RecurrenceParentId])
REFERENCES [dbo].[Appointments] ([AppointmentId])
GO

ALTER TABLE [dbo].[Appointments] CHECK CONSTRAINT [FK_Appointments_ParentAppointments]
GO
EDMX

--

<Schema Namespace="SafetyTrackerModel.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="SafetyTrackerModelStoreContainer">
      <EntitySet Name="Appointments" EntityType="SafetyTrackerModel.Store.Appointments" store:Type="Tables" Schema="dbo" />
      <AssociationSet Name="FK_Appointments_ParentAppointments" Association="SafetyTrackerModel.Store.FK_Appointments_ParentAppointments">
        <End Role="Appointments" EntitySet="Appointments" />
        <End Role="Appointments1" EntitySet="Appointments" />
      </AssociationSet>
    </EntityContainer>
    <EntityType Name="Appointments">
      <Key>
        <PropertyRef Name="AppointmentId" />
      </Key>
      <Property Name="AppointmentId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
      <Property Name="Description" Type="nvarchar" MaxLength="1024" />
      <Property Name="Start" Type="datetime" Nullable="false" />
      <Property Name="End" Type="datetime" Nullable="false" />
      <Property Name="Username" Type="varchar" Nullable="false" MaxLength="50" />
      <Property Name="RecurrenceRule" Type="nvarchar" MaxLength="1024" />
      <Property Name="RecurrenceState" Type="varchar" MaxLength="20" />
      <Property Name="RecurrenceParentId" Type="int" StoreGeneratedPattern="Identity" />
      <Property Name="Annotations" Type="nvarchar" MaxLength="50" />
      <Property Name="Application" Type="nvarchar" Nullable="false" MaxLength="100" />
    </EntityType>
    <Association Name="FK_Appointments_ParentAppointments">
      <End Role="Appointments" Type="SafetyTrackerModel.Store.Appointments" Multiplicity="0..1" />
      <End Role="Appointments1" Type="SafetyTrackerModel.Store.Appointments" Multiplicity="*" />
      <ReferentialConstraint>
        <Principal Role="Appointments">
          <PropertyRef Name="AppointmentId" />
        </Principal>
        <Dependent Role="Appointments1">
          <PropertyRef Name="RecurrenceParentId" />
        </Dependent>
      </ReferentialConstraint>
    </Association>
  </Schema></edmx:StorageModels>
<edmx:ConceptualModels>
  <Schema Namespace="SafetyTrackerModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
    <EntityContainer Name="SafetyTrackerEntities">
      <EntitySet Name="Appointments" EntityType="SafetyTrackerModel.Appointment" />
      <AssociationSet Name="FK_Appointments_ParentAppointments" Association="SafetyTrackerModel.FK_Appointments_ParentAppointments">
        <End EntitySet="Appointments" Role="Appointment" />
        <End EntitySet="Appointments" Role="Appointment1" />
      </AssociationSet>
      </EntityContainer>
    <EntityType Name="Appointment">
      <Key>
        <PropertyRef Name="AppointmentId" />
      </Key>
      <Property xmlns:a="http://schemas.microsoft.com/ado/2009/02/edm/annotation" Name="AppointmentId" Nullable="false" a:StoreGeneratedPattern="Identity" Type="Int32" />
      <Property Name="Description" MaxLength="1024" FixedLength="false" Unicode="true" Type="String" />
      <Property Name="Start" Nullable="false" Type="DateTime" />
      <Property Name="End" Nullable="false" Type="DateTime" />
      <Property Name="Username" Nullable="false" MaxLength="50" FixedLength="false" Unicode="false" Type="String" />
      <Property Name="RecurrenceRule" MaxLength="1024" FixedLength="false" Unicode="true" Type="String" />
      <Property Name="RecurrenceState" MaxLength="20" FixedLength="false" Unicode="false" Type="String" />
      <Property Name="Annotations" MaxLength="50" FixedLength="false" Unicode="true" Type="String" />
      <Property Name="Application" Nullable="false" MaxLength="100" FixedLength="false" Unicode="true" Type="String" />
      <NavigationProperty Name="ChildAppointments" Relationship="SafetyTrackerModel.FK_Appointments_ParentAppointments" FromRole="Appointment" ToRole="Appointment1" />
      <NavigationProperty Name="ParentAppointment" Relationship="SafetyTrackerModel.FK_Appointments_ParentAppointments" FromRole="Appointment1" ToRole="Appointment" />
    </EntityType>
    </Schema>
</edmx:ConceptualModels>
<edmx:Mappings>
  <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
    <EntityContainerMapping StorageEntityContainer="SafetyTrackerModelStoreContainer" CdmEntityContainer="SafetyTrackerEntities">
      <EntitySetMapping Name="Appointments">
        <EntityTypeMapping TypeName="SafetyTrackerModel.Appointment">
          <MappingFragment StoreEntitySet="Appointments"> <!-- [1] -->
            <ScalarProperty Name="Application" ColumnName="Application" />
            <ScalarProperty Name="Annotations" ColumnName="Annotations" />
            <ScalarProperty Name="RecurrenceState" ColumnName="RecurrenceState" />
            <ScalarProperty Name="RecurrenceRule" ColumnName="RecurrenceRule" />
            <ScalarProperty Name="Username" ColumnName="Username" />
            <ScalarProperty Name="End" ColumnName="End" />
            <ScalarProperty Name="Start" ColumnName="Start" />
            <ScalarProperty Name="Description" ColumnName="Description" />
            <ScalarProperty Name="AppointmentId" ColumnName="AppointmentId" />
          </MappingFragment>
        </EntityTypeMapping>
      </EntitySetMapping>
      <AssociationSetMapping Name="FK_Appointments_ParentAppointments" TypeName="SafetyTrackerModel.FK_Appointments_ParentAppointments" StoreEntitySet="Appointments">
        <EndProperty Name="Appointment1">
          <ScalarProperty Name="AppointmentId" ColumnName="AppointmentId" />
        </EndProperty>
        <EndProperty Name="Appointment">
          <ScalarProperty Name="AppointmentId" ColumnName="RecurrenceParentId" />
        </EndProperty>
        <Condition ColumnName="AppointmentId" IsNull="false" /> <!-- Problem Here -->
      </AssociationSetMapping>
      </EntityContainerMapping>
  </Mapping>
</edmx:Mappings>

As is I get the compiler error:

Condition cannot be specified for Column member 'AppointmentId' because it is marked with a 'Computed' or 'Identity' StoreGeneratedPattern.

If removed that error goes away, but simply introduces another one about:

Problem in mapping fragments starting at lines 3350, 3380:EntityTypes SafetyTrackerModel.Appointment are being mapped to the same rows in table Appointments. Mapping conditions can be used to distinguish the rows that these types are mapped to.

which happens to be the line above marked [1].

At this point I'm lost as to what I'm supposed to do. I've tried many, many things and ultimately I've run out of intelligent things to try and have entered the land of the cargo cult.

I would really like to understand what the problem is here.

EF can support recursive objects. You just have to import the model and EF will pick up the relationship and will allow you to do recursion.

See MSDN .

About your FK, I don't understand why you have a CHECK CONSTRAINT. Adding a FK should be like this :

ALTER TABLE Appointments
ADD FOREIGN KEY (RecurrenceParentId) REFERENCES Appointments(AppointmentId);

Maybe something went wrong with your FK creation and EF cannot handle it ?

Hope this helps !

Edit: haha, just saw it was asked 9 months ago ... Well, never mind :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM