Пошаговое руководство: наследование сопоставления типа «одна таблица на иерархию»
В данном разделе показана реализация наследования типа «одна таблица на иерархию» путем изменения концептуальной модели в модели EDM. Наследование типа «одна таблица на иерархию» использует одну таблицу базы данных для сопровождения данных для всех типов сущности в иерархии наследования. Дополнительные сведения о реализации наследования в модели EDM см. в разделе Наследование (модель EDM).
В данном пошаговом руководстве показана реализация наследования типа «одна таблица на иерархию» путем изменения модели EDM, используемой в приложении CourseManager (дополнительные сведения см. в подразделе «Предварительные условия» этого раздела).
В модели EDM CourseManager тип сущности Person имеет два свойства: HireDate и EnrollmentDate, которые относятся к новым типам сущностей (Instructor и Student соответственно), наследуемым от Person. Следующие шаги подводят итог реализации наследования типа «одна таблица на иерархию» в этом случае. Процедуры в этом пошаговом руководстве содержат более подробные сведения.
Создайте два новых типа сущности: Instructor и Student.
Выберите Person как базовый тип для каждого нового типа сущности.
Перенесите свойство HireDate с Person на Instructor и свойство EnrollmentDate с Person на Student.
Сделайте тип сущности Person абстрактным.
Сопоставьте тип сущности Instructor таблице Person со следующими двумя условиями: HireDate Is Not Null и EnrollmentDate Is Null.
Сопоставьте тип сущности Student таблице Person со следующими двумя условиями: EnrollmentDate Is Not Null и HireDate Is Null.
Предварительные требования
Для работы с этим пошаговым руководством необходимо построить приложение CourseManager. Дополнительные сведения и инструкции см. в разделе Краткое руководство по платформе Entity Framework. После построения этого приложения необходимо изменить модель EDM путем реализации наследования типа «одна таблица на иерархию». После этого можно будет расширить функциональность приложения, отображая посещаемость выбранного курса.
Примечание. |
---|
Приложение CourseManager используется в качестве отправной точки во многих разделах пошагового руководства в данной документации, поэтому рекомендуется использовать для данного пошагового руководства копию приложения CourseManager, а не вносить изменения в первоначальный код CourseManager. |
В этом пошаговом руководстве предполагается, что читатель обладает основными навыками работы со средой Visual Studio и платформой .NET Framework, а также навыками программирования на языке Visual C# или Visual Basic.
Реализация наследования типа «одна таблица на иерархию»
В этой процедуре будет изменена концептуальная часть модели EDM SchoolModel для реализации наследования типа «одна таблица на иерархию».
Реализация наследования типа «одна таблица на иерархию»
Откройте решение CourseManager в среде Visual Studio.
В обозревателе решений дважды щелкните файл School.edmx.
Файл School.edmx открывается в конструкторе модели EDM ADO.NET (в конструкторе сущностей).
Щелкните правой кнопкой мыши пустую часть области конструктора сущностей, укажите Добавить и выберите пункт Сущность.
Появится диалоговое окно Создание сущности.
Введите значение Instructor в поле Имя сущности и выберите пункт Person в раскрывающемся списке Базовый тип.
Нажмите ОК.
Новый тип сущности будет создан и отобразится в области конструктора.
Повторите шаги с 3-го по 5-ый, но на шаге 4 введите значение Student в поле Имя сущности.
Были созданы два новых типа сущности Instructor и Student, которые отображаются в области конструктора. Стрелка идет от новых типов сущности к типу сущности Person; это показывает, что тип Person является базовым для новых типов сущности.
Щелкните правой кнопкой мыши свойство HireDate (в разделе Скалярные свойства) типа сущности Person. Выберите команду Вырезать.
Щелкните правой кнопкой мыши свойство Скалярные свойства типа сущности Instructor и выберите пункт Вставить.
Щелкните правой кнопкой мыши свойство HireDate и выберите пункт Свойства.
В окне Свойства установите для свойства Допускает значение NULL значение false.
Повторите шаги с 7 по 10, при этом вырежьте свойство EnrollmentDate типа сущности Person и вставьте его в тип сущности Student.
Выберите тип сущности Person. В окне Свойства установите для свойства Абстрактный значение true.
Появляется окно с сообщением, что если задан абстрактный тип сущности, то все существующие сопоставления функции для данного типа сущности будут удалены. Нажмите ОК.
Примечание. Обычно нет необходимости использовать абстрактные типы для создания модели сценариев типа «одна таблица на иерархию». Абстрактные типы используются в этом примере для демонстрации их использования в моделях EDM.
Примечание. Для оставшихся шагов этой процедуры требуется окно Сведения о сопоставлении. Если это окно не отображается, щелкните правой кнопкой мыши область конструктора и выберите пункт Сведения о сопоставлении.
Выберите тип сущности Instructor и щелкните <Добавить таблицу или представление> в окне Сведения о сопоставлении.
Поле <Добавить таблицу или представление> станет раскрывающимся списком таблиц или представлений, которым выбранная сущность может быть сопоставлена.
Выберите пункт Person из раскрывающегося списка.
Окно Сведения о сопоставлении обновляется с учетом сопоставления столбцов по умолчанию и параметра для добавления условия.
Нажмите кнопку <Добавить условие>.
Поле <Добавить условие> становится раскрывающимся списком столбцов, для которых может быть выставлено условие.
Выберите пункт HireDate из раскрывающегося списка.
Появится другое поле <Добавить условие>.
В столбце Оператор окна Сведения о сопоставлении выберите Является из раскрывающегося списка.
В столбце Свойство/значение выберите Не NULL.
Нажмите кнопку <Добавить условие>.
Выберите пункт EnrollmentDate из раскрывающегося списка.
В столбце Оператор в раскрывающемся списке выберите Is.
В столбце Свойство/значение выберите NULL.
Примечание. Если свойство/значение используется в условии, оно не может быть также свойством сущности (если только условие не использует сравнение типа IS NULL или IS NOT NULL).
Повторите шаги с 13-го по 22-ый для типа сущности Student, но укажите условия HireDate Is Null и EnrollmentDate Is Not Null.
Теперь наследование типа «одна таблица на иерархию» успешно реализовано.
Создание пользовательского интерфейса
Далее добавьте кнопку в форму приложения CourseViewer, которая загружает и показывает форму Enrollment. После этого добавьте два элемента управления ComboBox и один элемент управления ListBox в форму Enrollment. Первый элемент управления ComboBox позволит выбрать отдел. Второй элемент управления ComboBox позволит выбрать курс в зависимости от отдела, выбранного в первом элементе управления ComboBox. Список студентов и преподавателей выбранного курса показывается в элементе управления ListBox.
Создание пользовательского интерфейса
Щелкните правой кнопкой мыши имя проекта CourseManager в окне Обозреватель решений, укажите пункт Добавить и выберите пункт Новый элемент.
Появится диалоговое окно Добавление нового элемента.
Выберите пункт Форма Windows, введите «Enrollment.vb» или «Enrollment.cs» в качестве имени формы (в зависимости от используемого языка) и нажмите кнопку Добавить.
Новая форма будет добавлена к проекту и открыта в конструкторе форм. Для имени формы установлено значение Enrollment; для текста установлено значение Enrollment.
Перетащите элемент управления ComboBox из области элементов в форму и укажите значение его имени departmentList в окне Свойства.
Перетащите другой элемент управления ComboBox в форму и укажите значение его имени courseList.
Перетащите элемент управления Listbox из области элементов в форму. Укажите значение его имени studentList в окне Свойства.
Дважды щелкните форму CourseViewer.cs или форму CourseViewer.vb в Обозревателе решений.
Форма CourseViewer откроется в конструкторе.
Перетащите элемент управления Button из области элементов в форму CourseViewer.
В окне Свойства укажите значение имени кнопки viewEnrollment и укажите текст кнопки View Enrollment.
Дважды нажмите кнопку viewEnrollment.
Откроется файл с фоновым кодом для формы CourseViewer.
Добавьте следующий код в обработчик события viewEnrollment_click:
Dim enrollmentForm As New Enrollment() enrollmentForm.Visible = True
Enrollment enrollmentForm = new Enrollment(); enrollmentForm.Visible = true;
Создание пользовательского интерфейса завершено.
Запрос к модели EDM
В этой процедуре будет выполнен запрос к модели EDM и результаты будут привязаны к элементам управления Windows Forms. Дополнительные сведения о привязке объектов к элементам управления см. в разделе Привязка объектов к элементам управления (платформа Entity Framework).
Запрос к модели EDM
При помощи формы Enrollment откройте конструктор форм и дважды щелкните форму Enrollment.
Откроется файл с фоновым кодом для формы Enrollment.
Для обращения к пространству имен модели EDM добавьте следующие инструкции: using (язык C#) или Imports (язык Visual Basic).
Imports System.Data.Objects Imports System.Data.Objects.DataClasses
using System.Data.Objects; using System.Data.Objects.DataClasses;
Добавьте свойство, представляющее контекст данных, к классу Enrollment.
' Create an ObjectContext instance based on SchoolEntity. Private schoolContext As SchoolEntities
// Create an ObjectContext instance based on SchoolEntity. private SchoolEntities schoolContext;
В обработчике события Enrollment_Load добавьте код для инициализации контекста объекта и привяжите элемент управления ComboBox к запросу, который возвращает все отделы и связанную информацию о курсе.
' Initialize the ObjectContext. schoolContext = New SchoolEntities() ' Define a query that returns all Department objects and ' related Course objects, ordered by name. Dim departmentQuery As ObjectQuery(Of Department) = _ schoolContext.Department.Include("Course") _ .OrderBy("it.Name") ' Bind the ComboBox control to the query, which is ' executed during data binding. Me.departmentList.DataSource = departmentQuery _ .Execute(MergeOption.OverwriteChanges) Me.departmentList.DisplayMember = "Name"
// Initialize the ObjectContext. schoolContext = new SchoolEntities(); // Define a query that returns all Department objects // and related Course objects, ordered by name. ObjectQuery<Department> departmentQuery = schoolContext.Department.Include("Course") .OrderBy("it.Name"); // Bind the ComboBox control to the query, which is // executed during data binding. this.departmentList.DataSource = departmentQuery .Execute(MergeOption.OverwriteChanges); this.departmentList.DisplayMember = "Name";
Вернитесь в конструктор формы Enrollment и дважды щелкните элемент управления departmentListComboBox.
Обработчик события departmentList_SelectedIndexChanged создан в файле с фоновым кодом.
Добавьте код в обработчик события для привязки элемента управления courseListComboBox к свойствам Course выбранного Department.
' Get the object for the selected department Dim department As Department = CType(Me.departmentList _ .SelectedItem, Department) ' Bind the ComboBox control Course properties of ' the selected Department. courseList.DataSource = department.Course courseList.DisplayMember = "Title"
// Get the object for the selected department. Department department = (Department)this.departmentList.SelectedItem; // Bind the ComboBox control Course properties of // the selected Department. courseList.DataSource = department.Course; courseList.DisplayMember = "Title";
Вернитесь в конструктор формы Enrollment и дважды щелкните элемент управления courseListComboBox.
Обработчик события courseList_SelectedIndexChanged создан в файле с фоновым кодом.
Добавьте код в обработчик события для отображения списка студентов в ListBox.
Me.studentList.Items.Clear() ' Get the CourseID from the selected Course. Dim course As Course = CType(Me.courseList.SelectedItem, _ Course) Dim courseId As Integer = course.CourseID ' Get all CourseGrade objects for the supplied CourseID Dim studentQuery As Course = schoolContext.Course.Where _ ("it.CourseID = @courseID", New ObjectParameter _ ("courseID", courseId)).Include("CourseGrade"). _ FirstOrDefault() ' Get all students for each CourseGrade For Each cg As CourseGrade In studentQuery.CourseGrade cg.PersonReference.Load() studentList.Items.Add(cg.Person.LastName + ", " + _ cg.Person.FirstName) Next studentList.Items.Add(" ") ' Get all Instructor types for the supplied CourseID Dim instructorQuery As Course = schoolContext.Course. _ Where("it.CourseID = @courseID", New ObjectParameter _ ("courseID", courseId)).Include("Person") _ .FirstOrDefault() ' Display each instructor for the specified Course For Each Instructor As Instructor In instructorQuery.Person Me.studentList.Items.Add("Instructor: " + Instructor. _ LastName + ", " + Instructor.FirstName) Next
studentList.Items.Clear(); // Get the CourseID from the selected Course. Course course = (Course)courseList.SelectedItem; int courseId = course.CourseID; // Get all CourseGrade types for the supplied CourseID Course studentQuery = schoolContext.Course.Where( "it.CourseID = @courseID", new ObjectParameter ("courseID", courseId)).Include("CourseGrade"). FirstOrDefault(); // Get all students for each CourseGrade foreach (CourseGrade cg in studentQuery.CourseGrade) { cg.PersonReference.Load(); studentList.Items.Add(cg.Person.LastName + ", " + cg.Person.FirstName); } studentList.Items.Add(" "); // Get all Instructor types for the supplied CourseID Course instructorQuery = schoolContext.Course.Where( "it.CourseID = @courseID", new ObjectParameter ("courseID", courseId)).Include("Person"). FirstOrDefault(); // Display each instructor for the specified course. foreach (Instructor instructor in instructorQuery.Person. OfType<Instructor>()) { studentList.Items.Add("Instructor: " + instructor. LastName + ", " + instructor.FirstName); }
Создание приложения завершено. Нажмите клавиши Ctrl+F5, чтобы запустить приложение. Нажмите кнопку View Enrollment, чтобы загрузить форму Enrollment. Посещаемость и список преподавателей выбранного курса показываются в ListBox.
Листинг кода
В этом разделе приводится конечная версия файла с фоновым кодом для формы Enrollment.
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Public Class Enrollment
' Create an ObjectContext instance based on SchoolEntity.
Private schoolContext As SchoolEntities
Private Sub Enrollment_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' Initialize the ObjectContext.
schoolContext = New SchoolEntities()
' Define a query that returns all Department objects and
' related Course objects, ordered by name.
Dim departmentQuery As ObjectQuery(Of Department) = _
schoolContext.Department.Include("Course") _
.OrderBy("it.Name")
' Bind the ComboBox control to the query, which is
' executed during data binding.
Me.departmentList.DataSource = departmentQuery _
.Execute(MergeOption.OverwriteChanges)
Me.departmentList.DisplayMember = "Name"
End Sub
Private Sub departmentList_SelectedIndexChanged(ByVal sender _
As System.Object, ByVal e As System.EventArgs) Handles _
departmentList.SelectedIndexChanged
' Get the object for the selected department
Dim department As Department = CType(Me.departmentList _
.SelectedItem, Department)
' Bind the ComboBox control Course properties of
' the selected Department.
courseList.DataSource = department.Course
courseList.DisplayMember = "Title"
End Sub
Private Sub courseList_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles _
courseList.SelectedIndexChanged
Me.studentList.Items.Clear()
' Get the CourseID from the selected Course.
Dim course As Course = CType(Me.courseList.SelectedItem, _
Course)
Dim courseId As Integer = course.CourseID
' Get all CourseGrade objects for the supplied CourseID
Dim studentQuery As Course = schoolContext.Course.Where _
("it.CourseID = @courseID", New ObjectParameter _
("courseID", courseId)).Include("CourseGrade"). _
FirstOrDefault()
' Get all students for each CourseGrade
For Each cg As CourseGrade In studentQuery.CourseGrade
cg.PersonReference.Load()
studentList.Items.Add(cg.Person.LastName + ", " + _
cg.Person.FirstName)
Next
studentList.Items.Add(" ")
' Get all Instructor types for the supplied CourseID
Dim instructorQuery As Course = schoolContext.Course. _
Where("it.CourseID = @courseID", New ObjectParameter _
("courseID", courseId)).Include("Person") _
.FirstOrDefault()
' Display each instructor for the specified Course
For Each Instructor As Instructor In instructorQuery.Person
Me.studentList.Items.Add("Instructor: " + Instructor. _
LastName + ", " + Instructor.FirstName)
Next
End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
namespace CourseManager
{
public partial class Enrollment : Form
{
// Create an ObjectContext instance based on SchoolEntity.
private SchoolEntities schoolContext;
public Enrollment()
{
InitializeComponent();
}
private void Enrollment_Load(object sender, EventArgs e)
{
// Initialize the ObjectContext.
schoolContext = new SchoolEntities();
// Define a query that returns all Department objects
// and related Course objects, ordered by name.
ObjectQuery<Department> departmentQuery =
schoolContext.Department.Include("Course")
.OrderBy("it.Name");
// Bind the ComboBox control to the query, which is
// executed during data binding.
this.departmentList.DataSource = departmentQuery
.Execute(MergeOption.OverwriteChanges);
this.departmentList.DisplayMember = "Name";
}
private void departmentList_SelectedIndexChanged(object sender,
EventArgs e)
{
// Get the object for the selected department.
Department department =
(Department)this.departmentList.SelectedItem;
// Bind the ComboBox control Course properties of
// the selected Department.
courseList.DataSource = department.Course;
courseList.DisplayMember = "Title";
}
private void courseList_SelectedIndexChanged(object sender,
EventArgs e)
{
studentList.Items.Clear();
// Get the CourseID from the selected Course.
Course course = (Course)courseList.SelectedItem;
int courseId = course.CourseID;
// Get all CourseGrade types for the supplied CourseID
Course studentQuery = schoolContext.Course.Where(
"it.CourseID = @courseID", new ObjectParameter
("courseID", courseId)).Include("CourseGrade").
FirstOrDefault();
// Get all students for each CourseGrade
foreach (CourseGrade cg in studentQuery.CourseGrade)
{
cg.PersonReference.Load();
studentList.Items.Add(cg.Person.LastName + ", " +
cg.Person.FirstName);
}
studentList.Items.Add(" ");
// Get all Instructor types for the supplied CourseID
Course instructorQuery = schoolContext.Course.Where(
"it.CourseID = @courseID", new ObjectParameter
("courseID", courseId)).Include("Person").
FirstOrDefault();
// Display each instructor for the specified course.
foreach (Instructor instructor in instructorQuery.Person.
OfType<Instructor>())
{
studentList.Items.Add("Instructor: " + instructor.
LastName + ", " + instructor.FirstName);
}
}
}
}
Следующие шаги
Было успешно реализовано наследование типа «одна таблица на иерархию» в модели EDM. Дополнительные сведения о задании модели EDM с наследованием типа «одна таблица на иерархию» см. в разделе Как определить модель с наследованием типа «одна таблица на иерархию» (платформа Entity Framework). Дополнительные сведения о привязке приложений при помощи платформы Entity Framework см. в разделе Руководство по программированию (платформа Entity Framework).
См. также
Другие ресурсы
Сценарии конструктора моделей EDM ADO.NET
Задачи средств модели EDM