Entity Framework: таблица для конкретного типа и уникальные идентификаторы для таблиц - PullRequest
0 голосов
/ 16 декабря 2010

У меня есть несколько таблиц, которые имеют только несколько свойств навигации и идентификатор.Я думаю, что здесь было бы интересно наследовать тип таблицы на конкретный тип .. (?) Это выглядит примерно так:

Контакт (базовый, абстрактный, не сопоставлен)
- ContactID
- свойства навигации для другихтаблицы (электронная почта, телефон, ..)

Лицо: контакт (сопоставлено с таблицей Лицо с различными свойствами + ContactID)
- различные свойства

Компания: контакт (сопоставлено сТаблица Company с различными свойствами + ContactID)
- различные свойства

Теперь, чтобы это работало, первичный ключ (contactID) должен быть уникальным для всех таблиц.Затем 2 варианта:
- GUID (не фанат)
- дополнительная таблица БД, генерирующая идентификаторы (только с полем ContactID, у производных таблиц есть FK), это не будет отображаться в EF.

Эта установка выполнима?Кроме того, что произойдет в ObjectContext?Какой временный ключ генерирует EF перед вызовом SaveChanges?Будет ли он уникальным среди объектов?

Спасибо за любые мысли.микрофон.

Ответы [ 3 ]

1 голос
/ 20 декабря 2010

(недостаточно места в разделе комментариев)

Я провел несколько тестов.
Дело в том, что вы в порядке, пока вы ТОЛЬКО указываете подтип, который запрашиваете (например, «Адрес» в вашем случае).
Но если вы запрашиваете базовый тип (даже если вам не нужна информация о подтипах), напр. только ContactPossibility.ID, сгенерированный SQL объединит все таблицы подтипов.
Таким образом, запрос вашей «отслеживаемой» коллекции ContactPossabilities может создать проблему производительности.

Я попытался обойти эту проблему, отключив базовую сущность и разделив унаследованные сущности на их собственную таблицу + общую таблицу, по сути, преобразовав TPT в TPC: это сработало нормально с концептуальной точки зрения (после большого редактирования edmx) ,
Пока я не понял, что это глупо ... :) Действительно, в этом случае вам всегда нужно объединять все базовые таблицы для запроса общих данных ...
(Хотя я не уверен в случае, описанном в конце этого поста, не пытался его проверить)

Так что я думаю, так как в основном мне нужно будет запросить конкретный тип (человек, компания, адрес, телефон, ...), сейчас все будет в порядке, и надеюсь, что MS исправит EF4.5.

Так что мне нужно быть осторожным при запросе, еще один интересный пример:
Допустим, вы хотите выбрать человека, а затем запросить его адрес, что-то вроде (пытался следовать вашему имени):
var person = from b in context.ContactEntities.OfType-Person-() where b.FirstName.StartsWith("X") select b;
var address = from a in context.ContactPossibilities.OfType-Address-() where **a.ContactEntity == person.FirstOrDefault()** select a;
это создаст объединение между всеми таблицами производных сущностей Contact и проблемами производительности: сгенерированный SQL принимает таблицу ContactPossibility и присоединяется к Address по ContactPossibilityID, затем объединяет объединение всех производных таблиц Contact, соединенных с базовой таблицей Contact , прежде чем, наконец, присоединиться к отфильтрованной таблице Person.

Однако рассмотрим следующую альтернативу:
var person = from b in context.ContactEntities.OfType-Person-() where b.FirstName.StartsWith("X")<BR> select b;
var address = from a in context.ContactPossibilities.OfType-Address-() where **a.ContactID == person.FirstOrDefault().ID** select a;
Это будет работать нормально: сгенерированный SQL принимает таблицу ContactPossibility и присоединяется к Address на ContactPossibilityID, а затем присоединяется к отфильтрованной таблице Person.

Mike.

1 голос
/ 16 декабря 2010

Мы используем похожую конструкцию с следующим дизайном БД:

ContactEntity

  • ID

ContactPossibility

  • ID
  • Позиция
  • ContactTypeID
  • ContactEntityID

Адрес

  • ID (= PK и FK для ContactPossibility.ID)
  • Улица
  • и т.д.

Телефон

  • ID (= PK и FK для ContactPossibility.ID)
  • номер
  • и т.д.

Человек

  • ID (= PK и FK для ContactEntity.ID)
  • 1046 * FirstName *
  • и т.д.

Компания

  • ID (= PK и FK для ContactEntity.ID)
  • Имя
  • и т.д.

В результате получается модель сущности в двух абстрактных классах: ContactEntity (CE) и ContactPossibility (CP) и несколько производных классов (Address = CP, Email = CP, Person = CE, Company = CE). Абстрактный и производные классы (строки в db;) имеют один и тот же уникальный идентификатор, потому что мы используем поле идентификатора в производных классах, которое является внешним ключом первичного ключа абстрактного класса. И мы используем Guid для этого, потому что наше программное обеспечение требует правильной работы в автономном режиме (не подключено к основной базе данных), и мы должны беспрепятственно решать проблемы синхронизации. Кроме того, в чем проблема с Guid?

Entity Framework действительно очень хорошо поддерживает этот дизайн БД / класса, и нам очень приятно от этого дизайна.

Эта настройка выполнима? Кроме того, что произойдет в ObjectContext? Какой временный ключ генерирует EF перед вызовом SaveChanges? Будет ли он уникальным среди объектов?

Предлагаемая настройка очень выполнима! ObjectContext работает нормально и без труда вставляет, обновляет и удаляет нужные таблицы для производных классов. Временные ключи? Они вам не нужны, если вы используете шаблон идентификатора для производных классов, который является как первичным, так и внешним ключом абстрактного класса. А с Guid вы можете быть уверены, что это уникально для всех объектов.

Более того: ForeignKey от CP до CE предоставит каждому CE (человеку, компании, пользователю и т. Д.) Отслеживаемую коллекцию возможностей контакта. Что действительно круто и удобно.

Надеюсь, это поможет ...

0 голосов
/ 20 декабря 2010

Хорошая работа, Майк!Я пойму дело.И, конечно, надеюсь, что MS придет с более элегантным способом ведения дел.А что касается запроса, я всегда должен делать сравнение на основе внешних ключей!

Пришлось дать ему другой ответ, потому что у него недостаточно репутации, чтобы отредактировать ваш ответ: (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...