Подтвердить что ты не робот

Entity Framework Complex Type vs Создание нового объекта

Я читаю о Entity Framework 4.0, и мне было интересно, почему я должен создавать сложный тип, а не новый Entity (Таблица) и отношение между ними?

4b9b3361

Ответ 1

Прекрасным примером является адрес. Использование сложного типа для адреса гораздо проще, чем для нового объекта. С сложными типами вам не нужно иметь дело с Первичным ключом. Подумайте о доступе к адресу, на сколько общих типов объектов будет иметь адрес (Business Units, People, Places). Представьте, что вы заполняете адреса многих людей и вам нужно установить ключ для каждого. С помощью сложных типов вы просто получаете доступ к внутренним свойствам их типа, и все готово. Вот пример MSDN примера. http://msdn.microsoft.com/en-us/library/bb738613.aspx

Ответ 2

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

Сложные типы не поддерживают ленивую загрузку, по крайней мере, не в EF 4.3. В качестве примера возьмем адресную ситуацию. У вас есть таблица Person с 15 столбцами, 5 из которых содержат адресную информацию для определенных лиц. Он имеет 50 тыс. Записей. Вы создаете объект Person для таблицы со сложным типом Address.

Если вам нужен список имен всех людей в вашей базе данных, вы бы сделали

var records = context.Persons;

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

var records = from p in context.Persons
              select new {
                LastName = p.LastName,
                FirstName = p.FirstName,
              }

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

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

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

Если в отличие от приведенного выше примера вам действительно нужны данные адреса почти в каждом запросе, который вы делаете, и действительно хотите иметь эти поля в таблице Person, просто добавьте их в объект Person. У вас не будет аккуратного адресного префикса, но это не совсем то, что потерять сон.

Но подождите, там еще!

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

Предположим, что у вас есть базовый класс сущности с именем EntityModel, который определяет идентификатор свойства. Это ключ для всех объектов сущности, поэтому теперь вы можете создавать

class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel

который вы затем можете использовать с Distinct() для фильтрации дубликатов из любого IQueryable типа T, где T - класс сущности. Сложный тип не может наследовать от EntityModel, потому что у него нет свойства ID, но это прекрасно, потому что вы все равно не будете использовать его.

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

public class GenericModelFilter<T> : where T : EntityModel

Ой, подождите, ваш сложный тип не имеет тип EntityModel. Теперь вам нужно усложнить дерево наследования объектов для размещения сложных типов или избавиться от контракта EntityModel и уменьшить видимость.

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

Expression<Func<T, bool>> GetPredicate() { ... }

теперь вы можете сделать что-то вроде этого:

personFilter = new GenericModelFilter<Person>();
companyFilter = new GenericModelFilter<Company>();
addressFilter = new GenericModelFilter<Address>(); //Complex type for Person

...

var query = from p in context.Persons.Where(personFilter.GetPredicate())
            join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID
            select p;

Это работает одинаково для всех объектов сущностей... кроме адреса с его особыми потребностями. Вы не можете присоединиться к нему, как в компании. Вы можете перейти к нему из Лица, но как вы применяете это выражение к нему и все еще заканчиваете работу с Лицом в конце? Теперь вам нужно взять момент и выяснить этот частный случай для простой системы, которая легко работает везде.

Эта модель повторяется на протяжении всего жизненного цикла проекта. Я говорю по опыту? Мне жаль, что я этого не сделал. Сложные типы продолжают останавливать ваш прогресс, как неудачный студент в конце класса, не добавляя ничего существенного. Сделайте себе одолжение и выберите фактические объекты объектов.

Ответ 3

Основываясь на концепциях проектирования, основанных на домене, совокупный корень может содержать один или несколько внутренних объектов. В этом случае внутренние объекты - внутри границы Aggregate Root - не имеют KEY. Родительский ключ будет применяться к ним или как-то так. Ваш ответ вернется к тому, чтобы сохранить все части внутри корня Aggregate, что делает вашу модель более надежной и намного более простой.