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.