Поделиться через


начало работы с базой данных 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).

изображение11

Вы можете настроить Entity Framework для создания Instructor сущностей и Student , которые наследуются от сущности Person . Этот шаблон создания структуры наследования сущностей из отдельной таблицы базы данных называется наследованием таблицы на иерархию (TPH).

Для курсов School база данных использует другой шаблон. Онлайн-курсы и курсы на месте хранятся в отдельных таблицах, каждая из которых имеет внешний ключ, указывающий на таблицу Course . Сведения, общие для обоих типов курсов, хранятся только в Course таблице.

image12

Вы можете настроить модель данных Entity Framework таким образом, чтобы сущности OnlineCourse и OnsiteCourse наследуются от сущности Course . Этот шаблон создания структуры наследования сущностей из отдельных таблиц для каждого типа, когда каждая отдельная таблица ссылается на таблицу, в которой хранятся данные, общие для всех типов, называется наследованием таблицы для каждого типа (TPT).

Шаблоны наследования TPH обычно обеспечивают более высокую производительность в Entity Framework, чем шаблоны наследования TPT, так как шаблоны TPT могут привести к сложным запросам на соединение. В этом пошаговом руководстве показано, как реализовать наследование TPH. Для этого выполните следующие действия.

  • Создайте Instructor типы сущностей и Student , производные от Person.
  • Перемещение свойств, относящихся к производным сущностям, из сущности Person в производные сущности.
  • Установка ограничений для свойств в производных типах.
  • Person Сделайте сущность абстрактной.
  • Сопоставьте каждую производную сущность с Person таблицей с условием, указывающим, как определить, представляет ли Person строка этот производный тип.

Добавление сущностей преподавателей и учащихся

Откройте файл SchoolModel.edmx , щелкните правой кнопкой мыши незанятую область в конструкторе, выберите Добавить, а затем — Сущность.

image01

В диалоговом окне Добавление сущности присвойте сущности Instructor имя и задайте для ее параметра Базовый тип значение Person.

image02

Нажмите кнопку ОК. Конструктор создает сущность, наследуемую Instructor от сущности Person . У новой сущности пока нет свойств.

image03

Повторите процедуру, чтобы создать Student сущность, которая также является производным от Person.

Только преподаватели имеют даты найма, поэтому необходимо переместить это свойство из сущности Person в Instructor сущность. В сущности щелкните правой PersonHireDate кнопкой мыши свойство и выберите вырезать. Затем щелкните правой кнопкой мыши свойства в сущности Instructor и выберите команду Вставить.

image04

Дата найма сущности Instructor не может иметь значение NULL. Щелкните правой HireDate кнопкой мыши свойство, выберите Пункт Свойства, а затем в окне Свойства измените на NullableFalse.

image05

Повторите процедуру, чтобы переместить EnrollmentDate свойство из сущности Person в Student сущность. Убедитесь, что для свойства также задано EnrollmentDate значение NullableFalse .

Теперь, Person когда сущность имеет только свойства, общие для Instructor сущностей и Student (кроме свойств навигации, которые вы не перемещаете), сущность можно использовать только в качестве базовой сущности в структуре наследования. Поэтому необходимо убедиться, что он никогда не рассматривается как независимая сущность. Щелкните правой Person кнопкой мыши сущность, выберите Свойства, а затем в окне Свойства измените значение свойства Abstract на True.

image06

Сопоставление сущностей преподавателя и учащегося с таблицей person

Теперь необходимо сообщить Entity Framework, как различать Instructor сущности и Student в базе данных.

Щелкните правой кнопкой Instructor мыши сущность и выберите Сопоставление таблиц. В окне Сведения о сопоставлении щелкните Добавить таблицу или представление и выберите Пользователь.

image07

Щелкните Добавить условие, а затем выберите HireDate.

image09

Измените значение оператора на Is, а значение / property — на Not Null.

image10

Повторите процедуру для сущности Students , указав, что эта сущность сопоставляется с таблицей Person , EnrollmentDate если столбец не имеет значения NULL. Затем сохраните и закройте модель данных.

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

Использование сущностей преподавателя и учащегося

При создании веб-страниц, которые работают с данными об учащихся Person и преподавателях, вы отправляете их в набор сущностей и фильтруете по свойству HireDate или EnrollmentDate , чтобы ограничить возвращаемые данные учащимися или преподавателями. Однако теперь при привязке каждого элемента управления источником данных к набору Person сущностей можно указать, что следует выбирать только Student типы сущностей или Instructor . Так как Entity Framework знает, как различать учащихся и преподавателей в Person наборе сущностей, для этого можно удалить Where параметры свойств, введенные вручную.

В Designer Visual Studio можно указать тип сущности, который EntityDataSource должен выбрать элемент управления, в раскрывающемся списке Configure Data SourceEntityTypeFilter мастера, как показано в следующем примере.

image13

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

image14

Тем не менее, так как вы изменили разметку для элементов управления для 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 + '%'" >

Запустите страницу, чтобы убедиться, что она по-прежнему работает, как и раньше.

image15

Обновите следующие страницы, созданные в предыдущих руководствах, чтобы они использовали новые 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>
    

    image16

  • В 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>
    

    image17

  • В 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>
    

    image18

    Разметка в 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>
    

    image19

В результате этих изменений вы улучшили поддержку приложения Университета Contoso несколькими способами. Вы переместили логику выбора и проверки из слоя пользовательского интерфейса (разметка ASPX ) и сделали ее неотъемлемой частью уровня доступа к данным. Это помогает изолировать код приложения от изменений, которые могут быть внесены в будущем в схему базы данных или модель данных. Например, вы можете решить, что учащиеся могут быть наняты в качестве помощников учителей и, следовательно, получить дату найма. Затем можно добавить новое свойство, чтобы отличать учащихся от преподавателей и обновить модель данных. Код в веб-приложении не требуется изменять, за исключением случаев, когда вы хотите показать дату найма для учащихся. Еще одним преимуществом добавления Instructor сущностей и Student является то, что ваш код более понятен, чем когда он ссылается на Person объекты, которые фактически были учащимися или преподавателями.

Теперь вы ознакомились с одним из способов реализации шаблона наследования в Entity Framework. В следующем руководстве вы узнаете, как использовать хранимые процедуры, чтобы иметь больший контроль над тем, как Entity Framework обращается к базе данных.