начало работы с базой данных Entity Framework 4.0 и веб-формы ASP.NET 4— часть 6
Пример веб-приложения Contoso University демонстрирует создание ASP.NET Web Forms приложений с помощью Entity Framework 4.0 и Visual Studio 2010. Сведения о серии учебников см. в первом руководстве серии
Реализация наследования типа «одна таблица на иерархию»
В предыдущем руководстве вы работали со связанными данными, добавляя и удаляя связи, а также добавляя новую сущность, связанную с существующей сущностью. В этом учебнике демонстрируется, как реализовать наследование в модели данных.
В объектно-ориентированном программировании можно использовать наследование, чтобы упростить работу со связанными классами. Например, можно создать Instructor
классы и Student
, производные Person
от базового класса. Можно создать те же типы структур наследования между сущностями в Entity Framework.
В этой части руководства вы не будете создавать новые веб-страницы. Вместо этого вы добавите производные сущности в модель данных и измените существующие страницы для использования новых сущностей.
Таблица на иерархию и наследование таблицы на тип
База данных может хранить сведения о связанных объектах в одной или нескольких таблицах. Например, в School
базе данных Person
таблица содержит сведения об учащихся и преподавателях в одной таблице. Некоторые столбцы относятся только к преподавателям (HireDate
), некоторые только к учащимся (EnrollmentDate
), а некоторые — к обоим (LastName
, FirstName
).
Вы можете настроить Entity Framework для создания Instructor
сущностей и Student
, которые наследуются от сущности Person
. Этот шаблон создания структуры наследования сущностей из отдельной таблицы базы данных называется наследованием таблицы на иерархию (TPH).
Для курсов School
база данных использует другой шаблон. Онлайн-курсы и курсы на месте хранятся в отдельных таблицах, каждая из которых имеет внешний ключ, указывающий на таблицу Course
. Сведения, общие для обоих типов курсов, хранятся только в Course
таблице.
Вы можете настроить модель данных Entity Framework таким образом, чтобы сущности OnlineCourse
и OnsiteCourse
наследуются от сущности Course
. Этот шаблон создания структуры наследования сущностей из отдельных таблиц для каждого типа, когда каждая отдельная таблица ссылается на таблицу, в которой хранятся данные, общие для всех типов, называется наследованием таблицы для каждого типа (TPT).
Шаблоны наследования TPH обычно обеспечивают более высокую производительность в Entity Framework, чем шаблоны наследования TPT, так как шаблоны TPT могут привести к сложным запросам на соединение. В этом пошаговом руководстве показано, как реализовать наследование TPH. Для этого выполните следующие действия.
- Создайте
Instructor
типы сущностей иStudent
, производные отPerson
. - Перемещение свойств, относящихся к производным сущностям, из сущности
Person
в производные сущности. - Установка ограничений для свойств в производных типах.
Person
Сделайте сущность абстрактной.- Сопоставьте каждую производную сущность с
Person
таблицей с условием, указывающим, как определить, представляет лиPerson
строка этот производный тип.
Добавление сущностей преподавателей и учащихся
Откройте файл SchoolModel.edmx , щелкните правой кнопкой мыши незанятую область в конструкторе, выберите Добавить, а затем — Сущность.
В диалоговом окне Добавление сущности присвойте сущности Instructor
имя и задайте для ее параметра Базовый тип значение Person
.
Нажмите кнопку ОК. Конструктор создает сущность, наследуемую Instructor
от сущности Person
. У новой сущности пока нет свойств.
Повторите процедуру, чтобы создать Student
сущность, которая также является производным от Person
.
Только преподаватели имеют даты найма, поэтому необходимо переместить это свойство из сущности Person
в Instructor
сущность. В сущности щелкните правой Person
HireDate
кнопкой мыши свойство и выберите вырезать. Затем щелкните правой кнопкой мыши свойства в сущности Instructor
и выберите команду Вставить.
Дата найма сущности Instructor
не может иметь значение NULL. Щелкните правой HireDate
кнопкой мыши свойство, выберите Пункт Свойства, а затем в окне Свойства измените на Nullable
False
.
Повторите процедуру, чтобы переместить EnrollmentDate
свойство из сущности Person
в Student
сущность. Убедитесь, что для свойства также задано EnrollmentDate
значение Nullable
False
.
Теперь, Person
когда сущность имеет только свойства, общие для Instructor
сущностей и Student
(кроме свойств навигации, которые вы не перемещаете), сущность можно использовать только в качестве базовой сущности в структуре наследования. Поэтому необходимо убедиться, что он никогда не рассматривается как независимая сущность. Щелкните правой Person
кнопкой мыши сущность, выберите Свойства, а затем в окне Свойства измените значение свойства Abstract на True.
Сопоставление сущностей преподавателя и учащегося с таблицей person
Теперь необходимо сообщить Entity Framework, как различать Instructor
сущности и Student
в базе данных.
Щелкните правой кнопкой Instructor
мыши сущность и выберите Сопоставление таблиц. В окне Сведения о сопоставлении щелкните Добавить таблицу или представление и выберите Пользователь.
Щелкните Добавить условие, а затем выберите HireDate.
Измените значение оператора на Is, а значение / property — на Not Null.
Повторите процедуру для сущности Students
, указав, что эта сущность сопоставляется с таблицей Person
, EnrollmentDate
если столбец не имеет значения NULL. Затем сохраните и закройте модель данных.
Выполните сборку проекта, чтобы создать новые сущности в виде классов и сделать их доступными в конструкторе.
Использование сущностей преподавателя и учащегося
При создании веб-страниц, которые работают с данными об учащихся Person
и преподавателях, вы отправляете их в набор сущностей и фильтруете по свойству HireDate
или EnrollmentDate
, чтобы ограничить возвращаемые данные учащимися или преподавателями. Однако теперь при привязке каждого элемента управления источником данных к набору Person
сущностей можно указать, что следует выбирать только Student
типы сущностей или Instructor
. Так как Entity Framework знает, как различать учащихся и преподавателей в Person
наборе сущностей, для этого можно удалить Where
параметры свойств, введенные вручную.
В Designer Visual Studio можно указать тип сущности, который EntityDataSource
должен выбрать элемент управления, в раскрывающемся списке Configure Data Source
EntityTypeFilter мастера, как показано в следующем примере.
А в окне Свойства можно удалить Where
ненужные значения предложений, как показано в следующем примере.
Тем не менее, так как вы изменили разметку для элементов управления для EntityDataSource
использования атрибута ContextTypeName
, вы не можете запустить мастер настройки источника данных для EntityDataSource
уже созданных элементов управления. Поэтому необходимо внести необходимые изменения, изменив разметку.
Откройте страницу Students.aspx . В элементе StudentsEntityDataSource
управления удалите Where
атрибут и добавьте EntityTypeFilter="Student"
атрибут . Теперь разметка будет выглядеть примерно так:
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Include="StudentGrades"
EnableDelete="True" EnableUpdate="True"
OrderBy="it.LastName" >
</asp:EntityDataSource>
Задание атрибута EntityTypeFilter
гарантирует, что EntityDataSource
элемент управления выберет только указанный тип сущности. Если вы хотите получить как типы сущностей, так Student
и Instructor
, этот атрибут не следует задавать. (Вы можете получить несколько типов сущностей с одним EntityDataSource
элементом управления, только если вы используете элемент управления для доступа к данным только для чтения. Если вы используете EntityDataSource
элемент управления для вставки, обновления или удаления сущностей, а сущность, к которому она привязана, может содержать несколько типов, вы можете работать только с одним типом сущности, и необходимо задать этот атрибут.)
Повторите процедуру для SearchEntityDataSource
элемента управления, за исключением удаления только той Where
части атрибута, которая выбирает Student
сущности, вместо удаления свойства полностью. Открывающий тег элемента управления теперь будет выглядеть следующим образом:
<asp:EntityDataSource ID="SearchEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People" EntityTypeFilter="Student"
Where="it.FirstMidName Like '%' + @StudentName + '%' or it.LastName Like '%' + @StudentName + '%'" >
Запустите страницу, чтобы убедиться, что она по-прежнему работает, как и раньше.
Обновите следующие страницы, созданные в предыдущих руководствах, чтобы они использовали новые Student
сущности Person
и Instructor
вместо сущностей, а затем запустите их, чтобы убедиться, что они работают так же, как и раньше:
В StudentsAdd.aspx добавьте
EntityTypeFilter="Student"
вStudentsEntityDataSource
элемент управления . Теперь разметка будет выглядеть примерно так:<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" EnableInsert="True" </asp:EntityDataSource>
В About.aspx добавьте
EntityTypeFilter="Student"
вStudentStatisticsEntityDataSource
элемент управления и удалитеWhere="it.EnrollmentDate is not null"
. Теперь разметка будет выглядеть примерно так:<asp:EntityDataSource ID="StudentStatisticsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Student" Select="it.EnrollmentDate, Count(it.EnrollmentDate) AS NumberOfStudents" OrderBy="it.EnrollmentDate" GroupBy="it.EnrollmentDate" > </asp:EntityDataSource>
В Instructors.aspx и InstructorsCourses.aspx добавьте
EntityTypeFilter="Instructor"
вInstructorsEntityDataSource
элемент управления и удалитеWhere="it.HireDate is not null"
. Разметка в Instructors.aspx теперь похожа на следующий пример:<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="false" EntitySetName="People" EntityTypeFilter="Instructor" Include="OfficeAssignment" EnableUpdate="True"> </asp:EntityDataSource>
Разметка в InstructorsCourses.aspx теперь будет выглядеть примерно так:
<asp:EntityDataSource ID="InstructorsEntityDataSource" runat="server" ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False" EntitySetName="People" EntityTypeFilter="Instructor" Select="it.LastName + ',' + it.FirstMidName AS Name, it.PersonID"> </asp:EntityDataSource>
В результате этих изменений вы улучшили поддержку приложения Университета Contoso несколькими способами. Вы переместили логику выбора и проверки из слоя пользовательского интерфейса (разметка ASPX ) и сделали ее неотъемлемой частью уровня доступа к данным. Это помогает изолировать код приложения от изменений, которые могут быть внесены в будущем в схему базы данных или модель данных. Например, вы можете решить, что учащиеся могут быть наняты в качестве помощников учителей и, следовательно, получить дату найма. Затем можно добавить новое свойство, чтобы отличать учащихся от преподавателей и обновить модель данных. Код в веб-приложении не требуется изменять, за исключением случаев, когда вы хотите показать дату найма для учащихся. Еще одним преимуществом добавления Instructor
сущностей и Student
является то, что ваш код более понятен, чем когда он ссылается на Person
объекты, которые фактически были учащимися или преподавателями.
Теперь вы ознакомились с одним из способов реализации шаблона наследования в Entity Framework. В следующем руководстве вы узнаете, как использовать хранимые процедуры, чтобы иметь больший контроль над тем, как Entity Framework обращается к базе данных.