Новые возможности Entity Framework 4.0

Том Дайкстра

Эта серия учебников основана на веб-приложении Contoso University, созданном с помощью серии учебников Getting Started with the Entity Framework. Если вы не прошли предыдущие уроки, для начала этого руководства вы можете скачать приложение, которое бы вы создали. Вы также можете скачать приложение , созданное в полной серии учебников. Если у вас есть вопросы об учебниках, их можно опубликовать на форуме ASP.NET Entity Framework.

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

  • Связи внешнего ключа.
  • Выполнение определяемых пользователем команд SQL.
  • Разработка на основе модели.
  • Поддержка POCO.

Кроме того, в этом руководстве кратко будет представлен подход code-first, функция, которая появится в следующем выпуске Entity Framework.

Чтобы начать учебник, запустите Visual Studio и откройте веб-приложение Contoso University, с которым вы работали в предыдущем руководстве.

Ассоциации Foreign-Key

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

Image01

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

Пример того, как внешние ключи в модели данных могут упростить код, рассмотрим, как нужно было бы закодировать страницу DepartmentsAdd.aspx без них. В сущности Department свойство Administrator является внешним ключом, соответствующим PersonID в сущности Person. Чтобы установить связь между новым отделом и его администратором, необходимо было задать значение свойства Administrator в обработчике событий ItemInserting связанного с данными элемента управления.

protected void DepartmentsDetailsView_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    e.Values["Administrator"] = administratorsDropDownList.SelectedValue;
}

Без внешних ключей в модели данных вы будете обрабатывать событие Inserting элемента управления источниками данных вместо события ItemInserting элемента управления связанного данных, чтобы получить ссылку на саму сущность перед добавлением сущности в набор сущностей. При наличии этой ссылки вы устанавливаете связь с помощью кода, например, в следующих примерах:

departmentEntityToBeInserted.PersonReference.EntityKey = new System.Data.EntityKey("SchoolEntities.Departments", "PersonID", Convert.ToInt32(administratorsDropDownList.SelectedValue));
departmentEntityToBeInserted.Person = context.People.Single(p => p.PersonID == Convert.ToInt32(administratorsDropDownList.SelectedValue));

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

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

Выполнение пользовательских команд SQL

В более ранних версиях Entity Framework не было простого способа создать собственные команды SQL на лету и запустить их. Либо Entity Framework динамически генерировал команды SQL для вас, либо вам нужно было создать хранимую процедуру и импортировать её как функцию. Версия 4 добавляет ExecuteStoreQuery и ExecuteStoreCommand методы ObjectContext класса, что упрощает передачу любого запроса непосредственно в базу данных.

Предположим, что администраторы Университета Contoso хотят иметь возможность выполнять массовые изменения в базе данных, не выполняя процесс создания хранимой процедуры и импорта его в модель данных. Их первый запрос — это страница, которая позволяет им изменить количество кредитов для всех курсов в базе данных. На веб-странице они хотят ввести число, чтобы умножить значение каждого Course столбца Credits строки.

Создайте новую страницу, использующую эталонную страницу Site.Master и назовите ее UpdateCredits.aspx. Затем добавьте следующую разметку в Content элемент управления с именем Content2:

<h2>Update Credits</h2>
    Enter the number to multiply the current number of credits by: 
    <asp:TextBox ID="CreditsMultiplierTextBox" runat="server"></asp:TextBox>
    <br /><br />
    <asp:Button ID="ExecuteButton" runat="server" Text="Execute" OnClick="ExecuteButton_Click" /><br /><br />
    Rows affected:
    <asp:Label ID="RowsAffectedLabel" runat="server" Text="0" ViewStateMode="Disabled"></asp:Label><br /><br />

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

Откройте UpdateCredits.aspx.cs и добавьте следующую using инструкцию и обработчик события кнопки Click :

using ContosoUniversity.DAL;
protected void ExecuteButton_Click(object sender, EventArgs e)
{
    using (SchoolEntities context = new SchoolEntities())
    {
        RowsAffectedLabel.Text = context.ExecuteStoreCommand("UPDATE Course SET Credits = Credits * {0}", CreditsMultiplierTextBox.Text).ToString();
    }
}

Этот код выполняет команду SQL Update с помощью значения в текстовом поле и использует метку для отображения количества затронутых строк. Перед запуском страницы запустите страницу Courses.aspx , чтобы получить изображение "до" некоторых данных.

Image02

Запустите UpdateCredits.aspx, введите "10" в качестве умножения и нажмите кнопку "Выполнить".

Image03

Снова запустите страницу Courses.aspx , чтобы просмотреть измененные данные.

Image04

(Если вы хотите задать количество кредитов обратно к исходным значениям, в UpdateCredits.aspx.cs замените Credits * {0} на Credits / {0} и повторно запустите страницу, введя 10 в качестве делителя.)

Дополнительные сведения о выполнении запросов, определяемых в коде, см. в разделе "Практическое руководство. Выполнение напрямую команд для источника данных".

разработка Model-First

В этих пошаговом руководстве вы сначала создали базу данных, а затем создали модель данных на основе структуры базы данных. В Entity Framework 4 можно начать с модели данных и создать базу данных на основе структуры модели данных. Если вы создаете приложение, для которого база данных еще не существует, подход на основе модели позволяет создавать сущности и связи, которые имеют смысл концептуально для приложения, не беспокоясь о физической реализации. (Это остаётся верным только на начальных этапах разработки. Однако в конечном итоге база данных будет создана и будет содержать рабочие данные, и повторное её создание из модели больше не будет практичным; на этом этапе вы вернётесь к подходу «сначала база данных».)

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

В обозревателе решений щелкните правой кнопкой мыши папку DAL и выберите "Добавить новый элемент". В диалоговом окне "Добавить новый элемент" в разделе "Установленные шаблоны " выберите "Данные ", а затем выберите шаблон модели данных сущности ADO.NET . Назовите новый файл AlumniAssociationModel.edmx и нажмите кнопку "Добавить".

Image06

Откроется мастер построения модели данных сущностей. На шаге "Выбор содержимого модели" выберите "Пустая модель " и нажмите кнопку "Готово".

Image07

Конструктор моделей данных сущностей открывается с пустой поверхностью дизайна. Перетащите элемент Entity из палитры инструментов на поверхность конструктора.

Image08

Измените имя сущности с Entity1 на Alumnus, измените имя свойства с Id на AlumnusId, и добавьте новое скалярное свойство с именем Name. Чтобы добавить новые свойства, нажмите клавишу ВВОД после изменения имени столбца Id или щелкните правой кнопкой мыши сущность и выберите "Добавить скалярное свойство". Тип по умолчанию для новых свойств — String, что подходит для этой простой демонстрации, но, конечно, можно изменить такие вещи, как тип данных в окне Свойств.

Создайте другую сущность таким же образом и назовите её Donation. Измените Id свойство на и добавьте скалярное свойство DonationId с именем DateAndAmount.

Image09

Чтобы добавить связь между этими двумя сущностями, щелкните правой кнопкой мыши Alumnus сущность, выберите "Добавить" и выберите "Связь".

Image10

Значения по умолчанию в диалоговом окне "Добавление ассоциации " — это то, что нужно (одно ко многим, включить свойства навигации, включить внешние ключи), поэтому просто нажмите кнопку "ОК".

Image11

Конструктор добавляет строку связи и свойство внешнего ключа.

Image12

Теперь вы готовы создать базу данных. Щелкните правой кнопкой мыши область конструктора и выберите "Создать базу данных из модели".

Image13

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

На шаге "Выбор подключения к данным" нажмите кнопку "Создать подключение".

Image14

В диалоговом окне "Свойства подключения" выберите локальный экземпляр SQL Server Express и назовите базу данных AlumniAssociation.

Image15

Нажмите кнопку "Да" , когда вам будет предложено создать базу данных. При повторном отображении шага выбора подключения к данным нажмите кнопку "Далее".

На шаге "Сводка" и "Параметры " нажмите кнопку "Готово".

Image18

Создается файл .sql с командами языка определения данных (DDL), но команды еще не выполнялись.

Image20

Используйте средство, например SQL Server Management Studio , чтобы запустить скрипт и создать таблицы, как можно было сделать при создании School базы данных для первого руководства в серии учебников по началу работы. (Если вы не скачали базу данных.)

Теперь вы можете использовать модель данных AlumniAssociation на своих веб-страницах так же, как используете модель данных School. Чтобы попробовать это, добавьте некоторые данные в таблицы и создайте веб-страницу, отображающую данные.

С помощью обозревателя серверов добавьте следующие строки в Alumnus таблицы и Donation таблицы.

Image21

Создайте новую веб-страницу с именем Alumni.aspx , использующую главную страницу Site.Master . Добавьте следующую разметку в Content элемент управления с именем Content2:

<h2>Alumni</h2>
    <asp:EntityDataSource ID="AlumniEntityDataSource" runat="server" 
        ContextTypeName="ContosoUniversity.DAL.AlumniAssociationModelContainer" EnableFlattening="False" 
        EntitySetName="Alumni">
    </asp:EntityDataSource>
    <asp:GridView ID="AlumniGridView" runat="server" 
        DataSourceID="AlumniEntityDataSource" AutoGenerateColumns="False"
        OnRowDataBound="AlumniGridView_RowDataBound"
        DataKeyNames="AlumnusId">
        <Columns>
            <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
            <asp:TemplateField HeaderText="Donations">
                <ItemTemplate>
                    <asp:GridView ID="DonationsGridView" runat="server" AutoGenerateColumns="False">
                        <Columns>
                            <asp:BoundField DataField="DateAndAmount" HeaderText="Date and Amount" />
                        </Columns>
                    </asp:GridView>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

Эта разметка создает вложенные GridView элементы управления: внешний для отображения имен выпускников и внутренний для отображения дат и сумм пожертвований.

Откройте Alumni.aspx.cs. using Добавьте инструкцию для уровня доступа к данным и обработчик события внешнего GridView элемента управленияRowDataBound:

using ContosoUniversity.DAL; 

// ...

protected void AlumniGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        var alumnus = e.Row.DataItem as Alumnus;
        var donationsGridView = (GridView)e.Row.FindControl("DonationsGridView");
        donationsGridView.DataSource = alumnus.Donations.ToList();
        donationsGridView.DataBind();
    }
}

Этот код связывает внутренний GridView элемент управления с помощью Donations свойства навигации сущности Alumnus текущей строки.

Запустите страницу.

Image22

(Примечание. Эта страница включена в скачиваемый проект, но для ее работы необходимо создать базу данных в локальном экземпляре SQL Server Express. База данных не включается в качестве файла .mdf в папку App_Data .)

Дополнительные сведения об использовании функции Model-First в Entity Framework см. Model-First in the Entity Framework 4.

Поддержка POCO

При использовании методологии проектирования на основе домена вы разрабатываете классы данных, представляющие данные и поведение, относящиеся к бизнес-домену. Эти классы должны быть независимыми от любой конкретной технологии, используемой для хранения (сохранения) данных; другими словами, они должны быть сохраняемость невнимания. Незнание сохраняемости также может упростить модульное тестирование класса, так как проект модульного теста может использовать любую технологию сохраняемости, наиболее удобную для тестирования. Более ранние версии Entity Framework предложили ограниченную поддержку незнания сохраняемости, так как классы сущностей должны были наследовать от EntityObject класса и, следовательно, включали большую часть функциональных возможностей Entity Framework.

Entity Framework 4 представляет возможность использовать классы сущностей, которые не наследуются от EntityObject класса, поэтому сохраняемость не учитывается. В контексте Entity Framework такие классы, как этот, обычно называются обычными объектами CLR (POCO или POCOs). Классы POCO можно создавать вручную или автоматически создавать их на основе существующей модели данных с помощью шаблонов средств преобразования текстовых шаблонов (T4), предоставляемых Entity Framework.

Дополнительные сведения об использовании POC в Entity Framework см. в следующих ресурсах:

разработка "Code-First"

Поддержка POCO в Entity Framework 4 по-прежнему требует создания модели данных и связывания классов сущностей с моделью данных. Следующий выпуск Entity Framework будет включать функцию, называемую разработкой Code First. Эта функция позволяет использовать Entity Framework с собственными классами POCO без необходимости использовать конструктор моделей данных или XML-файл модели данных. (Таким образом, этот параметр также называется только кодом; код-первый и только код относятся к одной функции Entity Framework.)

Дополнительные сведения об использовании подхода Code-First в разработке см. в следующих ресурсах:

Кроме того, новый учебник по MVC Code-First, который создает приложение, похожее на приложение Contoso University, будет опубликовано весной 2011 г. https://asp.net/entity-framework/tutorials

Дополнительная информация

В этом разделе представлен обзор новых возможностей Entity Framework, а также продолжение серии руководств по Entity Framework. Дополнительные сведения о новых функциях в Entity Framework 4, которые не рассматриваются здесь, см. в следующих ресурсах: