2012-02-23 3 views
1

Я использую EF с ТРС и у меня есть множественное наследование позволяет сказать, что у меня естьEntity Framework TPC с множественным наследованием

Employee (абстрактный)

Developer (наследуется от сотрудника)

SeniorDeveloper (наследуемого от разработчика)

Я вставил несколько строк в базу данных, и EF читает их правильно.

НО Когда я вставляю новую SeniorDeveloper, значения пишутся в SeniorDeveloper И таблицу базы данных разработчиков, следовательно, запрашивая только для разработчиков (context.Employees.OfType()) также получает недавно добавленные SeniorDevelopers.

Есть ли способ сказать EF, что он должен храниться только в одном столе или почему EF возвращается к стратегии TPT?

+0

Эти две проблемы не связаны. Вы уверены, что данные действительно находятся в таблице «Разработчики» = вы уверены, что правильно настроили TPC? Проблема с 'OfType' не связана с TPC/TPT. Это просто, как работает «OfType». –

+0

OfType действительно работал одинаково в tpt ... В любом случае, я вставил значения за руку в базу данных (разработчики для разработчиков и SeniorDevelopers ТОЛЬКО для SeniorDevelopers), а OfType () действительно предоставил мне только разработчиков и не разработчиков SeniorDevelopers, и что звучит немного странно для меня. Я установил все, как сказано здесь http://cockneycoder.wordpress.com/2010/11/25/entity-framework-and-concrete-table-pertyty-inheritance/ – relascope

ответ

1

Поскольку она не выглядит, как EF поддерживает множественное наследование с TPC, мы в конечном итоге с помощью TPC для Работника Developer и ТРТ между Разработчиком и SeniorDeveloper ...

+0

Неверно, что EF не " t поддерживает множественное наследование с помощью TPC. Для EF> = 4.1 он работает ('OfType' на типе просто переводит в UNION в SQL по таблицам для этого типа и всех производных типов). INSERTS только вставляются в таблицу вставленного типа, а не в таблицы базового типа. Поскольку EF 4.1 использует «ObjectContext» EF 4.0, я также сомневаюсь, что он не поддерживается в EF 4.0. – Slauma

1

Я считаю, что есть основания для этого, хотя я не вижу полной картины и могу просто спекулировать.

Ситуация

В самом деле, единственный способ (что я вижу) для EF, чтобы быть в состоянии перечислить только без старших разработчиков (ваш выполнение запроса использование регистра) в сценарии ТРТ, прочитав только Таблица Developer была бы с использованием дискриминатора, и мы знаем, что EF не использует ее в TPT/TPC-стратегиях.

Почему? Ну, помните, что все старшие разработчики составляют разработчиков, поэтому вполне естественно (и необходимо), чтобы у них была запись Developer, а также запись SeniorDeveloper.

Единственным исключением является то, что Developer - это абстрактный тип, и в этом случае вы можете использовать стратегию TPC для полного удаления таблицы Developer. В вашем случае, однако, Developer является бетонным.

Текущее решение

Вспоминая это, и без дискриминатора в Developer таблице, единственный способ определить, если любой разработчик не является старшим разработчиком, проверяя, если это не ведущий разработчик; другими словами, путем проверки отсутствия записи разработчика в таблице SeniorDeveloper или любой другой таблицы подтипов.

Это звучит немного очевидно, но теперь мы понимаем, почему таблица SeniorDeveloper должна использоваться и доступна, когда ее базовый тип (Разработчик) является конкретным (не абстрактным).

Текущая реализация

Я пишу это из памяти, так что я надеюсь, что это не так уж и выключен, но это также то, что Slauma упоминается в другом комментарии. Вероятно, вы хотите запустить профилировщик SQL и проверить это.

Способ, которым это реализовано, обратившись к UNION из выступов из таблиц. Эти прогнозы просто добавляют дискриминатор, объявляющий свой собственный тип каким-то закодированным способом [1]. В объединенном наборе строки затем могут быть отфильтрованы на основе этого дискриминатора.

[1] Если я правильно помню, это выглядит примерно так: 0X для базового типа, 0X0X для первого подтипа объединения, 0X1X для второго подтипа и т. Д.

Компромисс # 1

Мы уже можем определить компромисс: EF может либо сохранить дискриминатор в таблице, или он может «генерировать один» в «время выполнения».

  • Недостатки хранимого дискриминатора в том, что он менее эффективен в пространстве и, возможно, «уродлив» (если это аргумент). Преимуществами являются производительность поиска в очень конкретном случае (нам нужны только записи базы ).
  • Недостатки дискриминатора «времени выполнения» в том, что производительность поиска не так хороша для того же варианта использования. Преимущества в том, что он более эффективен в пространстве.

На первый взгляд кажется, что иногда мы можем предпочесть торговать небольшим количеством пространства для выполнения запросов, и EF не позволит нам.

В действительности, это не всегда ясно, когда; запрашивая UNION из двух таблиц, мы просто просматриваем два индекса вместо одного, а разница в производительности незначительна. При одном уровне наследования он не может быть хуже, чем 2x (поскольку все подтипы не пересекаются). Но подождите, больше.

Компромисс # 2

Помните, что я сказал, что преимущество производительности запасенного дискриминатора подхода будет появляться только в конкретном потребительном случае, когда мы LookUp записи базового типа. Почему это?

Ну, если вы ищете разработчиков, которые могут или не могут быть старшими разработчиками [2], вы вынуждены искать таблицу SeniorDeveloperв любом случае. Хотя это, опять же, кажется очевидным, что может быть менее очевидным, так это то, что EF не может знать заранее, если типы будут только одного типа. Это означает, что он должен был выдать два запросов в худшем случае: один в таблице Developer, и если в результирующем наборе есть еще один старший разработчик, второй в таблице SeniorDeveloper.

К сожалению, дополнительные туда и обратно вероятно имеет влияние больше производительности, чем объединение двух таблиц. (Я думаю, вероятно, я не проверил его.) Хуже того, он увеличивается для каждого подтипа, для которого есть строка в результирующем наборе. Представьте себе тип с 3, или 5 или даже 10 подтипами.

И это ваш компромисс № 2.

[2] Помните, что этот вид операции может исходить из любой части ваших приложений, тогда как разрешение компромисса должно выполняться глобально для удовлетворения всех процессов/приложений/пользователей. Также свяжите это с тем фактом, что команда EF должна сделать эти компромиссы для всех пользователей EF (хотя верно, что они могут добавить некоторую конфигурацию для этих видов компромиссов).

Возможной альтернативой

По запросам пакетирование SQL, можно было бы избежать множества туда и обратно. EF должен будет отправить процессуальную логику на сервер для условного поиска (T-SQL). Но поскольку мы уже установили в компромиссе №1, что преимущество во многих случаях, по всей вероятности, незначительно, я не уверен, что это когда-либо будет стоить усилий. Может быть, кто-то может открыть билет для этой проблемы, чтобы определить, имеет ли это смысл.

Заключение

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

Прямо сейчас, однако, я думаю, что EF выбрал справедливое решение. Странно, это почти чище.

Несколько замечаний

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

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

  • Вы также упомянули, что EF «отступит» к стратегии TPT. В случае Developer/SeniorDeveloper стратегия TPC будет иметь те же результаты, что и стратегия TPT, поскольку разработчик является конкретным. Если вам действительно нужна отдельная таблица, вы должны использовать стратегию TPH.

+0

+1 за отличную работу! во всяком случае, я не был в проекте (и на SO) некоторое время, поэтому я прочитал его сейчас. Хорошо объяснил! (не проверял) – relascope