Entity Framework Самостоятельные ссылки Иерархические многие ко многим - PullRequest
3 голосов
/ 03 марта 2010

ОК, у этой проблемы есть все.

Концептуально у меня есть ресурсная сущность, которая может иметь много дочерних ресурсов и много родительских ресурсов. Таблица ресурсов имеет два поля: ID и Имя, где ID является первичным ключом.

Чтобы завершить отношение «многие ко многим», я создал таблицу ResourceHierarchy, которая имеет два поля (Parent_ID, Child_ID) и два внешних ключа, каждое из которых ссылается на первичный ключ таблицы Resource (ID), а таблица ResourceHierarchy имеет составной первичный ключ (Parent_ID, Child_ID)

Теперь мы уже знаем, что каждый Ресурс может выступать в качестве Родителя или Дочернего по отношению к другим ресурсам, однако логически не у всех Ресурсов будет Родитель, но это не главное. В качестве примера, скажем, у меня есть следующие ресурсы в моей таблице ресурсов.

ID    Name
10000 Little House
10001 Font Door
10002 Roof
10003 Roof Tile
10004 Tile Monster

И в таблице ResourceHierarchy у нас есть следующие отношения.

Parent_ID Child_ID
10000     10001
10000     10002
10002     10003
10004     10003

Тогда Entity Framework генерирует Entity, пока что все хорошо ...

Если бы вы проверили сгенерированный код в файле edmx, вы бы увидели, что таблица ResourceHierarchy обрабатывается как отношение, а таблица ResourceHierarchy недоступна через код, поскольку она не рассматривается как объект.

Если бы это было все, что я хотел, то это сработало бы отлично.

Однако проблема начинается, когда я хочу добавить столбец количества в иерархию сущностей ресурсов. Например, у маленького дома есть только одна парадная дверь и одна крыша, но у ресурсов монстров крыши и черепицы может быть много черепиц крыши.

Итак, если мы добавим столбец Количество в таблицу ресурсов, то получим следующее.

ID    Name            Quantity
10000 Little House 1
10001 Font Door  1
10002 Roof   1
10003 Roof Tile  5
10004 Tile Monster 1

Это создает проблему, из-за которой монстр крыши и черепицы должен делиться 5 черепицами крыши. Поэтому, естественно, я бы попытался добавить столбец количества в таблицу ResourceHierarchy, однако, как только я это сделаю и обновлю сгенерированный код, теперь обрабатывает таблицу ResourceHierarchy как объект, а не как отношение, как было ранее. И теперь, чтобы вернуться к таблице ресурсов, мне нужно пройти через эту не концептуальную «сущность / отношение», которая не очень проста. Как будто у меня есть Entity в моей концептуальной модели, который будет использоваться только для обратного перехода к Resource Entity, и я даже не уверен, что Resource.Children.Add (r) создаст новые строки в таблице ResourceHierarchy в БД , Это как если бы я выбрал свойства, т. Е. Количество, сущности, которую я использую только как отношение.

В идеале таблица ResourceHierarchy должна иметь столбец Количество, похожий на этот.

Parent_ID Child_ID Quantity
10000     10001  1
10000     10002  1
10002     10003  8
10004  10003  13

И Ресурсный Сущность все еще будет иметь свойства навигации Дочерние, Родительские и каким-то образом получит доступ к столбцу Количество как свойство Ресурсного Сущности.

Я пытался объединить сгенерированный код с наличием столбца количества и отсутствием столбца количества, но было сгенерировано исключение, которое я интерпретирую как таблица ResourceHierarchy, которая может быть либо отношением, либо сущностью, но не обоими.

Пожалуйста, ПОМОГИТЕ!

Edmx кардинально меняется при добавлении и исключении столбца количества в таблице ResourceHierarchy в БД.

Вот пример сравнения, единственное отличие - это ResourceType, а ResourceHierarchy - ResourceTypeHierarchy.

Модель хранения SSDL не имеет изменений, кроме одного дополнительного свойства в ResourceTypeHierarchy EntityType, поэтому я не буду включать его ниже.

БЕЗ КОЛИЧЕСТВА КОЛИЧЕСТВА В РЕСУРСЕТИПЕХИЕРАРХИИ

RESOURCETYPEHIERARCHY - ОТНОШЕНИЕ

<!-- CSDL content -->
        <edmx:ConceptualModels>
          <Schema Namespace="MyModel" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
            <EntityContainer Name="MyEntities">
              <EntitySet Name="ResourceTypes" EntityType="MyModel.ResourceType" />
              <AssociationSet Name="ResourceTypeHierarchy" Association="MyModel.ResourceTypeHierarchy">
                <End Role="ResourceType" EntitySet="ResourceTypes" />
                <End Role="ResourceType1" EntitySet="ResourceTypes" /></AssociationSet></EntityContainer>
            <EntityType Name="ResourceType">
              <Key>
                <PropertyRef Name="ID" /></Key>
              <Property Type="Int32" Name="ID" Nullable="false" />
              <Property Type="String" Name="Type" Nullable="false" MaxLength="25" FixedLength="false" Unicode="false" />
              <NavigationProperty Name="Parents" Relationship="MyModel.ResourceTypeHierarchy" FromRole="ResourceType" ToRole="ResourceType1" />
              <NavigationProperty Name="Children" Relationship="MyModel.ResourceTypeHierarchy" FromRole="ResourceType1" ToRole="ResourceType" /></EntityType>
            <Association Name="ResourceTypeHierarchy">
              <End Type="MyModel.ResourceType" Role="ResourceType" Multiplicity="*" />
              <End Type="MyModel.ResourceType" Role="ResourceType1" Multiplicity="*" /></Association></Schema>
        </edmx:ConceptualModels>


<!-- C-S mapping content -->
        <edmx:Mappings>
          <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
            <EntityContainerMapping StorageEntityContainer="MyModelStoreContainer" CdmEntityContainer="MyEntities">
              <EntitySetMapping Name="ResourceTypes">

                <EntityTypeMapping TypeName="IsTypeOf(MyModel.ResourceType)">
                  <MappingFragment StoreEntitySet="ResourceType">
                    <ScalarProperty Name="ID" ColumnName="ID" />
                    <ScalarProperty Name="Type" ColumnName="Type" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
              <AssociationSetMapping Name="ResourceTypeHierarchy" TypeName="MyModel.ResourceTypeHierarchy" StoreEntitySet="ResourceTypeHierarchy">
                <EndProperty Name="ResourceType1">
                  <ScalarProperty Name="ID" ColumnName="Parent_ID" /></EndProperty>
                <EndProperty Name="ResourceType">
                  <ScalarProperty Name="ID" ColumnName="Child_ID" /></EndProperty></AssociationSetMapping></EntityContainerMapping>
          </Mapping>
        </edmx:Mappings>

С КОЛИЧЕСТВОМ КОЛОННЫ НА РЕСУРСЕТИПЕХИЕРАРХИИ

RESOURCETYPEHIERARCHY СУЩЕСТВУЕТ СУЩЕСТВОМ

<!-- C-S mapping content -->
<edmx:Mappings>
  <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2008/09/mapping/cs">
    <EntityContainerMapping StorageEntityContainer="MyModelStoreContainer" CdmEntityContainer="MyEntities">
      <EntitySetMapping Name="ResourceTypes">

        <EntityTypeMapping TypeName="IsTypeOf(MyModel.ResourceType)">
          <MappingFragment StoreEntitySet="ResourceType">
            <ScalarProperty Name="ID" ColumnName="ID" />
            <ScalarProperty Name="Type" ColumnName="Type" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
      <EntitySetMapping Name="ResourceTypeHierarchies">

        <EntityTypeMapping TypeName="IsTypeOf(MyModel.ResourceTypeHierarchy)">
          <MappingFragment StoreEntitySet="ResourceTypeHierarchy">
            <ScalarProperty Name="Child_ID" ColumnName="Child_ID" />
            <ScalarProperty Name="Parent_ID" ColumnName="Parent_ID" />
            <ScalarProperty Name="Quantity" ColumnName="Quantity" /></MappingFragment></EntityTypeMapping></EntitySetMapping>
      <AssociationSetMapping Name="FK_Child" TypeName="MyModel.FK_Child" StoreEntitySet="ResourceTypeHierarchy">
        <EndProperty Name="ResourceTypeHierarchy">
          <ScalarProperty Name="Child_ID" ColumnName="Child_ID" />
          <ScalarProperty Name="Parent_ID" ColumnName="Parent_ID" /></EndProperty>
        <EndProperty Name="ResourceType">
          <ScalarProperty Name="ID" ColumnName="Child_ID" /></EndProperty></AssociationSetMapping>
      <AssociationSetMapping Name="FK_Parent" TypeName="MyModel.FK_Parent" StoreEntitySet="ResourceTypeHierarchy">
        <EndProperty Name="ResourceTypeHierarchy">
          <ScalarProperty Name="Child_ID" ColumnName="Child_ID" />
          <ScalarProperty Name="Parent_ID" ColumnName="Parent_ID" /></EndProperty>
        <EndProperty Name="ResourceType">
          <ScalarProperty Name="ID" ColumnName="Parent_ID" /></EndProperty></AssociationSetMapping></EntityContainerMapping>
  </Mapping>
</edmx:Mappings>

1 Ответ

1 голос
/ 20 сентября 2010

Я считаю, что это работает, как предполагалось. Я имею в виду, что если вы поместите в таблицу атрибут, который устанавливает связь между двумя сущностями, эта таблица ДОЛЖНА (по крайней мере, из теории представления данных) быть представлена ​​как правильная сущность. Если вы тщательно обдумаете это, вы поймете, почему. Упомянутое вами количество является атрибутом отношения, а не какой-либо из связанных сущностей. Таким образом, эта таблица должна рассматриваться как объект, а не как отношение.

Теперь о том, как это преодолеть, одна вещь, которая приходит мне в голову (хотя я не уверен, что это полностью решит вашу проблему), - это относиться к отношениям, как вы изначально думали (без количества), и иметь другую таблицу. (это будет сопоставлено с сущностью в вашей модели), которая хранит количество определенного отношения. Я думаю, что эта таблица может даже иметь ограничение внешнего ключа в вашей базе данных на исходную таблицу отношений, хотя этот внешний ключ не может быть сопоставлен с отношением в вашей модели (потому что у вас нет объекта для конечной точки), но это все же позволяет поддерживать целостность данных в хранилище.

Надеюсь, это поможет, Витор

...