Entity Framework 4 Таблица для иерархии - как определить навигационные свойства для детей?

В настоящее время у меня есть модель Entity Framework 4.0 с Table Per Type (TPT), но есть несколько проблем с производительностью (много операторов LOJ/CASE), а также сопоставление проблем между двумя конкретными доменами (многие -в-многим).

Я решил попробовать TPH.

У меня есть объект, называемый Местоположение ", который является абстрактным, и базой для всех других объектов.

Затем у меня есть Страна "," Город "," Состояние "," Улица ", и т.д., которые все происходят из Местоположение.

" LocationType" является dicriminator.

Эта часть работает нормально, но у меня возникают проблемы с определением навигационных свойств для производных типов.

Например, " State" имеет единственную " Страну", поэтому я должен иметь возможность сделать это:

var state = _ctx.Locations.OfType<State>().Include("Country").First();
var countryForState = state.Country;

Но для этого должно существовать навигационное свойство, называемое "Страна", на основе "State". Как мне это сделать? Когда я создаю модель из базы данных, у меня есть одна таблица со всеми FK, указывающими на записи в той же таблице:

alt text

(ПРИМЕЧАНИЕ: я создал эти FK вручную в БД).

Но FK помещаются как nav в объект Местоположение, так как я могу перенести эти навигационные свойства на производные объекты? Я не могу скопировать + вставить навигаторы, и я не могу "создать новое навигационное свойство", потому что он не позволит мне определить начальную/конечную роль.

Как мы это делаем?

Также неясно, с TPH, если мы сможем сделать это во-первых, или мы должны начать с БД, исправить модель, а затем повторно сгенерировать БД. Мне еще предстоит найти хороший пример в Интернете о том, как определить navs для детей с TPH.

ПРИМЕЧАНИЕ. Я не хочу делать код сначала. Мое текущее решение имеет TPT с EDMX и чистые POCO, я надеюсь не влиять на модель/репозитории домена (если это возможно) и просто обновлять модель/базу данных EF.

ИЗМЕНИТЬ

По-прежнему нет решения - однако я пытаюсь сделать сначала модель, а Add → New Association, что на самом деле позволяет мне добавить навигацию к производным объектам. Но когда я пытаюсь "Генерировать базу данных из модели", она по-прежнему пытается создать таблицы для "Location_Street", "Location_Country" и т.д. Это почти так же, как TPH не может быть сначала выполнена.

ИЗМЕНИТЬ

Вот моя текущая модель:

alt text

Ошибка проверки, которую я получаю:

Ошибка 1 Ошибка 3002: проблема при сопоставлении фрагменты, начинающиеся с линии 359: Потенциальное нарушение времени выполнения таблицы (Locations.LocationId): столбцы (Locations.LocationId) отображаются на EntitySet NeighbourhoodZipCode's свойства (NeighbourhoodZipCode.Neighbourhood.LocationId) на концептуальной стороне, но они не сформировать свойства ключа EntitySet (NeighbourhoodZipCode.Neighbourhood.LocationId, NeighbourhoodZipCode.ZipCode.LocationId).

Просто подумал, что я продолжу редактирование этого вопроса с правлением относительно того, где я сейчас. Я начинаю задаваться вопросом, возможна ли TPH с саморегуляцией FK.

ИЗМЕНИТЬ

Итак, я выяснил вышеприведенную ошибку, потому что мне не хватало таблицы соединений для Neighborhood-ZipCode для многих.

Добавление таблицы соединений (и сопоставление навигаторов с этим) решило указанную выше ошибку.

Но теперь я получаю эту ошибку:

Ошибка 3032: проблема с отображением фрагменты, начинающиеся с линий 373, 382: Элементы состояния "Locations.StateLocationId" имеют значения повторяющихся условий.

Если я посмотрю на CSDL, вот сопоставление ассоциаций для "CountyState" (в штате есть много округов, округ имеет 1 состояние):

<AssociationSetMapping Name="CountyState" TypeName="Locations.CountyState" StoreEntitySet="Locations">
   <EndProperty Name="State">
      <ScalarProperty Name="LocationId" ColumnName="StateLocationId" />
   </EndProperty>
   <EndProperty Name="County">
      <ScalarProperty Name="LocationId" ColumnName="LocationId" />
   </EndProperty>
   <Condition ColumnName="StateLocationId" IsNull="false" />
</AssociationSetMapping>

Это то, что Condition ColumnName="StateLocationId", которое жалуется, потому что ZipCodeState также связывает это условие.

Но я не понимаю. Дискриминаторы для всех объектов уникальны (я проверял тройку), и я бы подумал, что это допустимый сценарий:

  • У округа есть одно состояние, обозначенное командой StateLocationId (Таблица мест)
  • ZipCode имеет одно состояние, обозначенное как StateLocationId (Таблица мест)

Это неверно в TPH?

Ответ 1

Итак, я решил несколько моих проблем, но я ударил кирпичную стену.

Прежде всего, когда вы создаете саморегуляционную FK в стороне базы данных, когда вы пытаетесь "Обновить модель из базы данных", Entity Framework добавит эти навигационные свойства к основному базовому типу, поскольку у нее нет явного смысла TPH - вам нужно сделать это на стороне модели.

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

WRT эта ошибка:

Ошибка 3032: проблема с отображением фрагментов, начинающихся с строк 373, 382: У местоположений членов условий .StateLocationId 'имеют повторяющиеся значения условий.

Это было потому, что у меня был FK, называемый "Location_State", который я пытался использовать для отношения "ZipCode_State", и отношения "City_State", которое не работает (по-прежнему не знаю, почему).

Итак, чтобы решить это, мне пришлось добавить дополнительные столбцы и дополнительный FK - один, называемый "ZipCode_State", а другой - "City_State" - очевидно, он должен быть 1-1 между navs и физическими FK.

Location.LocationType не имеет значения по умолчанию и не имеет значения NULL. Для хранения данных сущности требуется значение столбца.

Это мое поле дискриминатора. В стороне базы данных она не может быть нулевой.

Я прочитал темы об этой проблеме, и они сказали, что вам нужно изменить отношения от 0.. * до 1.. * - но мои отношения уже были 1.. *.

Если вы посмотрите на таблицу фактической базы данных "Locations" выше, все FK будут иметь значение NULL (они должны быть). Поэтому я начал задаваться вопросом, должны ли мои отношения быть 0.. *.

Но они являются нулевыми из-за TPH - не все "местоположения" будут иметь "состояние". Но если это местоположение является "городом", тогда у него должно быть "состояние".

Мои чувства были еще более утешены этим вопросом SO: ADO EF - Сопоставление сопоставлений ошибок между производными типами в TPH

Я действительно пытался обходным путем (до того, как я даже наткнулся на него), и обходной путь не работает для меня. Я даже попытался изменить все отношения от 1.. * до 0.. *, и до сих пор не повезло.

Слишком много времени здесь, я вернулся к TPT.

В конце дня, с TPH, у меня был бы смехотворно большой стол с множеством избыточных столбцов с нулевым значением. СОВМЕСТНО, это более эффективно. Но, по крайней мере, с TPT мне не требуется иметь NULL и саморегуляторные FK.

Если у кого-то есть решение этой проблемы, дайте мне знать. Но до тех пор, я придерживался TPT.