Сложные типы — конструктор EF
В этом разделе показано, как сопоставить сложные типы с конструктором Entity Framework (EF Designer) и как запрашивать сущности, содержащие свойства сложного типа.
На следующем рисунке показаны основные окна, которые используются при работе с конструктором EF.
Примечание.
При создании концептуальной модели в списке ошибок могут появиться предупреждения об несопоставленных сущностях и сопоставлениях. Эти предупреждения можно игнорировать, так как после выбора создания базы данных из модели ошибки будут удалены.
Что такое сложный тип
Сложные типы — это нескалярные свойства типов сущности, которые позволяют организовать в сущностях скалярные свойства. Подобно сущностям, сложные типы состоят из скалярных свойств или свойств других сложных типов.
При работе с объектами, представляющими сложные типы, следует учитывать следующее:
- Сложные типы не имеют ключей и поэтому не могут существовать независимо. Сложные типы могут существовать только как свойства типов сущностей или других сложных типов.
- Сложные типы не могут участвовать в сопоставлениях и не могут содержать свойства навигации.
- Свойства сложного типа не могут иметь значение NULL. **InvalidOperationException **возникает при вызове DbContext.SaveChanges и обнаружен сложный объект NULL. Скалярные свойства сложных объектов могут иметь значение NULL.
- Сложные типы не могут наследоваться от других сложных типов.
- Необходимо определить сложный тип как класс.
- EF обнаруживает изменения элементов в объекте сложного типа при вызове DbContext.DetectChanges . Entity Framework автоматически вызывает DetectChanges при вызове следующих элементов: DbSet.Find, DbSet.Local, DbSet.Remove, DbSet.Add, DbSet.Attach, DbContext.SaveChanges, DbContext.GetValidationErrors, DbContext.Entry, DbChangeTracker.Entries.
Рефакторинг свойств сущности в новый сложный тип
Если у вас уже есть сущность в концептуальной модели, может потребоваться рефакторинг некоторых свойств в свойство сложного типа.
В области конструктора выберите одно или несколько свойств (за исключением свойств навигации) сущности, а затем щелкните правой кнопкой мыши и выберите рефакторинг —> перейти к новому сложному типу.
В браузер модели добавляется новый сложный тип с выбранными свойствами. Сложному типу присваивается имя по умолчанию.
Сложное свойство только что созданного типа заменит выбранные свойства. Все сопоставления свойств будут сохранены.
Создание сложного типа
Можно также создать новый сложный тип, который не содержит свойств существующей сущности.
Щелкните правой кнопкой мыши папку "Сложные типы " в браузере моделей, наведите указатель на добавление сложного типа.... Кроме того, можно выбрать папку "Сложные типы " и нажать клавишу INSERT на клавиатуре.
Новый сложный тип будет добавлен в папку с именем по умолчанию. Теперь можно добавить свойства в тип.
Добавление свойств в сложный тип
Свойства сложного типа могут иметь как скалярные, так и существующие сложные типы. Однако свойства сложного типа не могут иметь циклических ссылок. Например, сложный тип OnsiteCourseDetails не может иметь свойство сложного типа OnsiteCourseDetails.
Добавить свойство к сложному типу можно любым из следующих способов.
Щелкните правой кнопкой мыши сложный тип в браузере модели, наведите указатель на "Добавить", а затем наведите указатель на скалярное свойство или сложное свойство, а затем выберите нужный тип свойства. Кроме того, можно выбрать сложный тип и нажать клавишу INSERT на клавиатуре.
Новое свойство будет добавлено к сложному типу с именем по умолчанию.
ИЛИ -
Щелкните правой кнопкой мыши свойство сущности в области EF Designer и выберите "Копировать", а затем щелкните правой кнопкой мыши сложный тип в браузере модели и выберите " Вставить".
Переименование сложного типа
При переименовании сложного типа все ссылки на тип обновляются по всему проекту.
Медленно дважды щелкните сложный тип в браузере моделей. Имя будет выбрано в режиме редактирования.
ИЛИ -
Щелкните правой кнопкой мыши сложный тип в браузере модели и выберите "Переименовать".
ИЛИ -
Выберите сложный тип в браузере моделей и нажмите клавишу F2.
ИЛИ -
Щелкните правой кнопкой мыши сложный тип в браузере модели и выберите "Свойства". Измените имя в окне "Свойства ".
Добавление существующего сложного типа в сущность и сопоставление свойств с столбцами таблицы
Щелкните правой кнопкой мыши сущность, наведите указатель на добавление нового и выберите "Сложное свойство". Свойство сложного типа с именем по умолчанию будет добавлено к сущности. Свойству назначается тип по умолчанию (выбранный из имеющихся сложных типов).
Назначьте нужный тип свойству в окне свойств . После добавления свойства сложного типа к сущности необходимо сопоставить ее свойства со столбцами таблицы.
Щелкните правой кнопкой мыши тип сущности в области конструктора или в браузере моделей и выберите сопоставления таблиц. Сопоставления таблиц отображаются в окне сведений о сопоставлении.
Разверните узел Карты на <узел имени> таблицы. Появится узел сопоставления столбцов.
Разверните узел сопоставления столбцов. Появится список всех столбцов таблицы. Свойства по умолчанию (если таковые имеются), с которыми сопоставляются столбцы, перечислены в заголовке Value/Property .
Выберите столбец, который нужно сопоставить, и щелкните правой кнопкой мыши соответствующее поле "Значение/свойство ". Отобразится раскрывающийся список всех скалярных свойств.
Выберите соответствующее свойство.
Повторите шаги 6 и 7 для каждого столбца таблицы.
Примечание.
Чтобы удалить сопоставление столбцов, выберите столбец, который требуется сопоставить, и щелкните поле "Значение/свойство ". Затем выберите "Удалить " из раскрывающегося списка.
Сопоставление импорта функции с сложным типом
Импорт функций основан на хранимых процедурах. Чтобы сопоставить импорт со сложным типом, столбцы, возвращаемые соответствующей хранимой процедурой, должны соответствовать свойствам сложного типа по числу и должны иметь типы хранения, совместимые с типами свойств.
Дважды щелкните импортированную функцию, которую необходимо сопоставить с сложным типом.
Задайте параметры для нового импорта функции следующим образом.
Укажите хранимую процедуру, для которой создается импорт функции в поле "Имя хранимой процедуры". Это поле представляет собой раскрывающийся список, содержащий все хранимые процедуры, которые имеются в модели хранения.
Укажите имя импорта функции в поле "Имя импорта функции".
Выберите "Сложный " в качестве возвращаемого типа, а затем укажите конкретный сложный тип возвращаемого значения, выбрав соответствующий тип из раскрывающегося списка.
Нажмите кнопку ОК. В концептуальной модели создается запись импорта функции.
Настройка сопоставления столбцов для импорта функций
- Щелкните правой кнопкой мыши импорт функции в браузере модели и выберите "Сопоставление импорта функций". Откроется окно сведений о сопоставлении и отображается сопоставление по умолчанию для импорта функции. Стрелки указывают сопоставления между значениями столбцов и значениями свойств. По умолчанию предполагается, что имена столбцов совпадают с именами свойств сложного типа. Имена столбцов по умолчанию отображаются серым текстом.
- Если необходимо, измените имена столбцов таким образом, чтобы они совпадали с именами столбцов, возвращаемых хранимой процедурой, соответствующей импорту функции.
Удаление сложного типа
При удалении сложного типа он удаляется из концептуальной модели. Кроме того, удаляются сопоставления для всех экземпляров типа. Однако ссылки на тип не обновляются. Например, если в браузере модели сущность имеет свойство сложного типа типа ComplexType1 и ComplexType1, соответствующее свойство сущности не обновляется. Модель не проверяется, так как она содержит сущность, которая ссылается на удаленный сложный тип. Обновить или удалить ссылки на удаленные сложные типы можно с помощью конструктора сущностей.
Щелкните правой кнопкой мыши сложный тип в браузере модели и выберите "Удалить".
ИЛИ -
В браузере моделей выберите сложный тип и нажмите на клавиатуре клавишу DELETE.
Запрос сущностей, содержащих свойства сложного типа
В следующем коде показано, как выполнить запрос, возвращающий коллекцию объектов типа сущностей, содержащих свойство сложного типа.
using (SchoolEntities context = new SchoolEntities())
{
var courses =
from c in context.OnsiteCourses
order by c.Details.Time
select c;
foreach (var c in courses)
{
Console.WriteLine("Time: " + c.Details.Time);
Console.WriteLine("Days: " + c.Details.Days);
Console.WriteLine("Location: " + c.Details.Location);
}
}