#entity-framework-4 #linq-to-entities #ef-database-first #database-first #table-per-hierarchy
#entity-framework-4 #linq-to-entities #ef-database-first #база данных-первая #таблица для каждой иерархии
Вопрос:
Я знаю, что это не должно быть тривиальным, но пока не смог найти решение…
Работа с моделью EF4 DB-First, использование LINQ-to-Entities с POCOs, которые будут использоваться приложением MVC3.
У меня есть три объекта Customer
, CustomerAdress
и поиск CustomerAddressType
.
Customer CustomerAddress CustomerAddressType
---------- ---------------- -------------------
CustomerId (PK) CustomerAddressId (PK) CustomerAddressTypeId (PK)
LastName CustomerId (FK) Description (Values: Mailing, Billing)
FirstName CustomerAddressTypeId (FK)
MiddleInitial Address
.... City
State
Zip
StartDate
EndDate
Как вы можете видеть, CustomerAddress
имеет FK CustomerAddressTypeId
, который определяет, какой это тип адреса, т.е. для рассылки или для выставления счетов.
Я хотел бы:
- Есть возможность сделать что-то вроде этого:
Customer.CustomerAddress.OfType<MailingAddress>
получить коллекцию почтовых адресов для клиента. - Иметь свойства
CurrentMailingAddress
иCurrentBillingAddress
, которые в будущем возвращали бы единственный экземплярCustomerAddress.OfType<>
с наивысшимStartDate
значениемEndDate
и, в конечном счете. - Было бы также неплохо использовать
Address
сквозныеZip
свойства и преобразовать эти свойства в сложный типAddress
.
Я попытался создать 2 унаследованных объекта из CustomerAddress
(предполагая, что это стратегия TPH [таблица для иерархии]): MailingAddress
и BillingAddress
, CustomerAddressTypeId
являющаяся дискриминатором. Я сделал это в конструкторе моделей, и как только я попытался добавить вторую унаследованную сущность, она сказала мне, что свойства с этими именами уже существуют, и не позволила мне переименовать их, чтобы они соответствовали свойствам первой сущности.
Есть идеи, как этого добиться? Пожалуйста, отключите это для меня 🙂 Спасибо!!!
Ответ №1:
Это не так тривиально. TPH будет возможен, но вы должны поместить все свойства в базу CustomerAddress
и вывести две дочерние сущности, которые не будут содержать никаких свойств, потому что все свойства являются общими (= должны быть в родительском). Вы будете использовать CustomerAddressTypeId
в качестве дискриминатора, и из-за этого вы не сможете отобразить это поле как свойство в сущности. Я также не уверен, что у вас может быть поле как в дискриминаторе, так и в сопоставлении ассоциаций (это на самом деле хорошая домашняя работа для меня). В противном случае вы не сможете сопоставить связь между CustomerAddress
и CustomerAddressType
.
Оба CurrentMailingAddress
и CurrentBillingAddress
являются вычисляемыми свойствами, и они не являются частью сопоставления. Вам решать реализовать их логику в вашей частичной части Customer
сущности.
Я не понимаю последнего пункта с Zip
и сложным типом.
Комментарии:
1. Спасибо, Ладислав. Думаю, отвечая на ваш пост, я начну с обратной стороны. 🙂 1)
Address
,City
,State
,Zip
— Я хотел бы провести рефакторинг в сложный тип, но не был уверен, что это доставит мне огорчения в будущем (я думаю, что все должно быть в порядке). 2) Причина, по которой я упомянул текущий * адрес, заключается в том, что именно там я хотел бы использовать CustomerAddress. Тип<>. 3) Я попробую и дам вам знать, как я разбираюсь.2. Хорошо, я создал 2 объекта
CustomerBillingAddress
иCustomerMailingAddress
с базовым типомCustomerAddress
. Установите отображение таблицы наCustomerAddress
и столбец дискриминатора для каждого объектаCustomerAddressTypeId
с соответствующим значением. Затем, когда я перехожу к проверке модели, я получаю следующую ошибку:3.
Error 1 Error 3023: Problem in mapping fragments starting at lines 1146, 1169, 1175:Column CustomerAddresses.AddressTypeId has no default value and is not nullable. A column value is required to store entity data. An Entity with Key (PK) will not round-trip when: (PK is in 'CustomerAddresses' EntitySet AND Entity is type [Entities.CustomerAddress])
. Я попытался удалить столбец дискриминатора ‘CustomerAddressTypeId` из базового объектаCustomerAddress
, тем самым разорвав связь сCustomerAddressType
, но все равно появляется то же сообщение.4. Хорошо, я думаю, что я устранил ошибку проверки модели… Пришлось: 1) для объекта
CustomerAddress
изменить свойство на Abstract: True (для создания абстрактного класса); 2) Удалить объектCustomerAddressType
; 3) Удалить столбец дискриминатораCustomerAddressTypeId
из базового объектаCustomerAddress
. Пока не было возможности проверить в коде, что все работает так, как ожидалось, но скоро опубликую.5. Хорошо, я наконец смог проверить, и это работает, но Ладислав, как вы упомянули, я не могу использовать оба способа, чтобы
CustomerAddressTypeId
быть одновременно ассоциацией и дискриминатором. Итак, мне пришлось потерять ассоциацию, что не имеет большого значения.