начало работы с entity Framework 4.0 Database First и ASP.NET 4 веб-формы — часть 2
Пример веб-приложения Contoso University демонстрирует создание ASP.NET Web Forms приложений с помощью Entity Framework 4.0 и Visual Studio 2010. Сведения о серии учебников см. в первом руководстве серии
Элемент управления EntityDataSource
В предыдущем руководстве вы создали веб-сайт, базу данных и модель данных. В этом руководстве вы работаете с элементом EntityDataSource
управления, который предоставляет ASP.NET, чтобы упростить работу с моделью данных Entity Framework. Вы создадите GridView
элемент управления для отображения и редактирования данных учащихся, DetailsView
элемент управления для добавления новых учащихся и DropDownList
элемент управления для выбора отдела (который вы будете использовать позже для отображения связанных курсов).
Обратите внимание, что в этом приложении вы не будете добавлять проверку входных данных на страницы, которые обновляют базу данных, и некоторые из операций обработки ошибок не будут столь надежными, как это требуется в рабочем приложении. В этом руководстве основное внимание уделяется Entity Framework и не дает ему слишком долгого времени. Дополнительные сведения о добавлении этих функций в приложение см. в разделах Проверка ввода данных пользователем в веб-страницы ASP.NET и Обработка ошибок в ASP.NET страниц и приложений.
Добавление и настройка элемента управления EntityDataSource
Сначала вы настроите EntityDataSource
элемент управления для чтения Person
сущностей из People
набора сущностей.
Убедитесь, что у вас открыта среда Visual Studio и что вы работаете с проектом, созданным в части 1. Если вы не создавали проект с момента создания модели данных или с момента последнего изменения, внесенного в него, выполните сборку проекта сейчас. Изменения в модели данных не становятся доступными для конструктора до тех пор, пока проект не будет построен.
Создайте веб-страницу с помощью шаблона главной страницы веб-формы и назовите ее Students.aspx.
Укажите Site.Master в качестве страницы master. Все страницы, создаваемые для этих учебников, будут использовать эту страницу master.
В представлении исходного кода добавьте заголовок h2
в Content
элемент управления с именем Content2
, как показано в следующем примере:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Student List</h2>
</asp:Content>
На вкладке Данныепанели элементов перетащите элемент EntityDataSource
управления на страницу, перетащите его под заголовок и измените идентификатор на StudentsEntityDataSource
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Student List</h2>
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server">
</asp:EntityDataSource>
</asp:Content>
Перейдите в режим конструктора , щелкните смарт-тег элемента управления источником данных и щелкните Настроить источник данных , чтобы запустить мастер настройки источника данных .
На шаге мастера Настройка ObjectContext выберите SchoolEntities в качестве значения именованного подключения, а в качестве значения DefaultContainerName выберите SchoolEntities. Нажмите кнопку Далее.
Примечание. Если на этом этапе появится следующее диалоговое окно, необходимо выполнить сборку проекта, прежде чем продолжить.
На шаге Настройка выбора данных выберите Люди в качестве значения EntitySetName. В разделе Выбрать убедитесь, что выбрано поле Выбрать проверка. Затем выберите параметры для включения обновления и удаления. Когда все будет готово, нажмите кнопку Готово.
Настройка правил базы данных для разрешения удаления
Вы создадите страницу, которая позволяет пользователям удалять учащихся из Person
таблицы, которая имеет три связи с другими таблицами (Course
, StudentGrade
и OfficeAssignment
). По умолчанию база данных не позволяет удалить строку в Person
, если в одной из других таблиц есть связанные строки. Вы можете сначала вручную удалить связанные строки или настроить для базы данных автоматическое удаление их при удалении Person
строки. Для записей учащихся в этом руководстве вы настроите базу данных для автоматического удаления связанных данных. Так как учащиеся могут иметь связанные строки только в StudentGrade
таблице, необходимо настроить только одну из трех связей.
Если вы используете файл School.mdf , скачанный из проекта, который входит в это руководство, этот раздел можно пропустить, так как эти изменения конфигурации уже выполнены. Если вы создали базу данных с помощью скрипта, настройте ее, выполнив следующие процедуры.
В Обозреватель сервера откройте схему базы данных, созданную в части 1. Щелкните правой кнопкой мыши связь между Person
и StudentGrade
(линия между таблицами), а затем выберите Свойства.
В окне Свойства разверните инструкции INSERT и UPDATE Specification и задайте для свойства DeleteRule значение Каскад.
Сохраните и закройте схему. Если вам будет предложено обновить базу данных, нажмите кнопку Да.
Чтобы убедиться, что модель сохраняет сущности, которые находятся в памяти, синхронизированы с тем, что делает база данных, необходимо задать соответствующие правила в модели данных. Откройте SchoolModel.edmx, щелкните правой кнопкой мыши линию связи между Person
и StudentGrade
, а затем выберите Свойства.
В окне Свойства задайте для end1 OnDelete значение Каскад.
Сохраните и закройте файл SchoolModel.edmx , а затем перестройте проект.
Как правило, при изменении базы данных можно синхронизировать модель несколькими способами:
- Для некоторых типов изменений (например, добавления или обновления таблиц, представлений или хранимых процедур) щелкните правой кнопкой мыши конструктор и выберите Обновить модель из базы данных , чтобы конструктор автоматически внесет изменения.
- Повторно создайте модель данных.
- Внесите обновления вручную, как это.
В этом случае вы могли бы повторно создать модель или обновить таблицы, затронутые изменением связи, но затем потребуется снова изменить имя поля (с FirstName
на FirstMidName
).
Использование элемента управления GridView для чтения и обновления сущностей
В этом разделе вы будете GridView
использовать элемент управления для отображения, обновления или удаления учащихся.
Откройте файл Students.aspx или перейдите в режим конструктора . На вкладке Данныепанели элементов перетащите GridView
элемент управления справа от EntityDataSource
элемента управления, назовите его StudentsGridView
, щелкните смарт-тег и выберите StudentsEntityDataSource в качестве источника данных.
Щелкните Обновить схему (нажмите кнопку Да , если появится запрос на подтверждение), а затем выберите Включить разбиение по страницам, Включить сортировку, Включить редактирование и Включить удаление.
Щелкните Изменить столбцы.
В поле Выбранные поля удалите PersonID, LastName и HireDate. Как правило, ключ записи не отображается для пользователей, дата найма не относится к учащимся, и вы помещаете обе части имени в одно поле, поэтому вам потребуется только одно из полей имени.)
Выберите поле FirstMidName и щелкните Преобразовать это поле в TemplateField.
Сделайте то же самое для EnrollmentDate.
Нажмите кнопку ОК , а затем переключитесь в исходное представление. Остальные изменения будет проще выполнять непосредственно в разметке. Разметка GridView
элемента управления теперь выглядит так, как показано в следующем примере.
<asp:GridView ID="StudentsGridView" runat="server" AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="PersonID"
DataSourceID="StudentsEntityDataSource">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:TemplateField HeaderText="FirstMidName" SortExpression="FirstMidName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="EnrollmentDate" SortExpression="EnrollmentDate">
<EditItemTemplate>
<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Первый столбец после поля команды — это поле шаблона, в котором в настоящее время отображается имя. Измените разметку для этого поля шаблона, чтобы она выглядела так, как показано в следующем примере:
<asp:TemplateField HeaderText="Name" SortExpression="LastName">
<EditItemTemplate>
<asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>'></asp:TextBox>
<asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
<asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
В режиме отображения два Label
элемента управления отображают имя и фамилию. В режиме редактирования предоставляются два текстовых поля, чтобы можно было изменить имя и фамилию. Как и в случае с элементами Label
управления в режиме отображения, выражения и Eval
используются Bind
точно так же, как и в ASP.NET элементов управления источником данных, которые подключаются непосредственно к базам данных. Единственное отличие заключается в том, что вы указываете свойства сущности вместо столбцов базы данных.
Последний столбец представляет собой поле шаблона, в котором отображается дата регистрации. Измените разметку для этого поля так, чтобы она выглядела так, как показано в следующем примере:
<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
<EditItemTemplate>
<asp:TextBox ID="EnrollmentDateTextBox" runat="server" Text='<%# Bind("EnrollmentDate", "{0:d}") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="EnrollmentDateLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
В режиме отображения и редактирования строка формата "{0,d}" приводит к отображению даты в формате "краткая дата". (На компьютере может быть настроено отображение этого формата, отличного от изображений экрана, показанных в этом руководстве.)
Обратите внимание, что в каждом из этих полей шаблона конструктор использовал Bind
выражение по умолчанию, но вы изменили его на Eval
выражение в элементах ItemTemplate
. Выражение Bind
делает данные доступными в GridView
свойствах элемента управления на случай, если необходимо получить доступ к данным в коде. На этой странице вам не нужно получать доступ к этим данным в коде, поэтому вы можете использовать Eval
, что является более эффективным. Дополнительные сведения см. в статье Получение данных из элементов управления данными.
Изменение разметки элемента управления EntityDataSource для повышения производительности
В разметке для EntityDataSource
элемента управления удалите атрибуты ConnectionString
и и DefaultContainerName
замените их атрибутом ContextTypeName="ContosoUniversity.DAL.SchoolEntities"
. Это изменение следует вносить каждый раз при создании EntityDataSource
элемента управления, если только вам не нужно использовать соединение, отличное от жестко закодированного в классе контекста объекта. Использование атрибута ContextTypeName
обеспечивает следующие преимущества:
- Повышенная производительность.
EntityDataSource
Когда элемент управления инициализирует модель данных с помощьюConnectionString
атрибутов иDefaultContainerName
, он выполняет дополнительную работу по загрузке метаданных для каждого запроса. Это необязательно при указании атрибутаContextTypeName
. - Отложенная загрузка включена по умолчанию в созданных классах контекста объекта (например, в
SchoolEntities
этом руководстве) в Entity Framework 4.0. Это означает, что свойства навигации автоматически загружаются со связанными данными прямо при необходимости. Отложенная загрузка более подробно описана далее в этом руководстве. - Любые настройки, примененные к классу контекста объекта (в данном случае классу
SchoolEntities
), будут доступны для элементов управления, использующихEntityDataSource
элемент управления . Настройка класса контекста объекта — это расширенная тема, которая не рассматривается в этой серии учебников. Дополнительные сведения см. в разделе Расширение созданных типов Entity Framework.
Теперь разметка будет похожа на следующий пример (порядок свойств может отличаться):
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EntitySetName="People"
EnableDelete="True" EnableUpdate="True">
</asp:EntityDataSource>
Атрибут EnableFlattening
ссылается на функцию, которая требовалась в более ранних версиях Entity Framework, так как столбцы внешнего ключа не были представлены в качестве свойств сущности. Текущая версия позволяет использовать связи внешних ключей, что означает, что свойства внешнего ключа предоставляются для всех связей, кроме "многие ко многим". Если у сущностей есть свойства внешнего ключа и нет сложных типов, для этого атрибута False
можно оставить значение . Не удаляйте атрибут из разметки, так как значение по умолчанию — True
. Дополнительные сведения см. в разделе Сведение объектов (EntityDataSource).
Запустите страницу, и вы увидите список учащихся и сотрудников (вы будете фильтровать только учащихся в следующем руководстве). Имя и фамилия отображаются вместе.
Чтобы отсортировать отображение, щелкните имя столбца.
Щелкните Изменить в любой строке. Отображаются текстовые поля, в которых можно изменить имя и фамилию.
Кнопка Удалить также работает. Нажмите кнопку Удалить для строки с датой регистрации, и строка исчезнет. (Строки без даты регистрации представляют преподавателей, и вы можете получить ошибку целостности данных. В следующем руководстве вы отфильтруете этот список, чтобы включить только учащихся.)
Отображение данных из свойства навигации
Теперь предположим, что вы хотите узнать, сколько курсов регистрируется каждый учащийся. Entity Framework предоставляет эти сведения в свойстве навигации StudentGrades
сущности Person
. Так как структура базы данных не позволяет зарегистрироваться учащегося в курсе без присвоения оценки, в этом руководстве можно предположить, что наличие строки в StudentGrade
строке таблицы, связанной с курсом, совпадает с тем, что и зачисление в курс. (Свойство Courses
навигации предназначено только для преподавателей.)
При использовании атрибута ContextTypeName
EntityDataSource
элемента управления Entity Framework автоматически получает сведения для свойства навигации при доступе к его свойству. Это называется отложенной загрузкой. Однако это может быть неэффективным, так как это приводит к отдельному вызову базы данных каждый раз, когда требуются дополнительные сведения. Если требуются данные из свойства навигации для каждой сущности, возвращаемой элементом EntityDataSource
управления, эффективнее получить связанные данные вместе с самой сущностью в одном вызове базы данных. Это называется неотложной загрузкой, и вы указываете неотложную загрузку для свойства навигации, задав Include
свойство EntityDataSource
элемента управления .
В Students.aspx нужно показать количество курсов для каждого учащегося, поэтому лучше всего выбрать загрузку. Если вы отображали всех учащихся, но отображали количество курсов только для некоторых из них (что потребовало бы написания кода в дополнение к разметке), отложенная загрузка может быть лучшим выбором.
Откройте students.aspx или перейдите в него, перейдите в режим конструктора , выберите StudentsEntityDataSource
и в окне Свойства задайте для свойства Include значение StudentGrades. (Если вы хотите получить несколько свойств навигации, можно указать их имена, разделенные запятыми, например StudentGrades, Courses.)
Переключитесь в представление источника . В элементе StudentsGridView
управления после последнего asp:TemplateField
элемента добавьте следующее новое поле шаблона:
<asp:TemplateField HeaderText="Number of Courses">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("StudentGrades.Count") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Eval
В выражении можно ссылаться на свойство StudentGrades
навигации . Поскольку это свойство содержит коллекцию, оно имеет Count
свойство, которое можно использовать для отображения количества курсов, в которых учащийся зарегистрирован. В следующем руководстве вы узнаете, как отображать данные из свойств навигации, содержащих отдельные сущности, а не коллекции. (Обратите внимание, что нельзя использовать BoundField
элементы для отображения данных из свойств навигации.)
Запустите страницу, и вы увидите, сколько курсов зарегистрирован каждый учащийся.
Использование элемента управления DetailsView для вставки сущностей
Следующим шагом является создание страницы с элементом DetailsView
управления, который позволит добавлять новых учащихся. Закройте браузер и создайте новую веб-страницу с помощью страницы master Site.Master. Назовите страницу StudentsAdd.aspx, а затем переключитесь на представление источника .
Добавьте следующую разметку, чтобы заменить существующую разметку Content
для элемента управления с именем Content2
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Add New Students</h2>
<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
EnableInsert="True" EntitySetName="People">
</asp:EntityDataSource>
<asp:DetailsView ID="StudentsDetailsView" runat="server"
DataSourceID="StudentsEntityDataSource" AutoGenerateRows="False"
DefaultMode="Insert">
<Fields>
<asp:BoundField DataField="FirstMidName" HeaderText="First Name"
SortExpression="FirstMidName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name"
SortExpression="LastName" />
<asp:BoundField DataField="EnrollmentDate" HeaderText="Enrollment Date"
SortExpression="EnrollmentDate" />
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
</asp:Content>
Эта разметка создает элемент EntityDataSource
управления, аналогичный созданному в Students.aspx, за исключением включения вставки. Как и в случае с элементом GridView
управления, связанные поля DetailsView
элемента управления кодируются точно так же, как и для элемента управления данными, который напрямую подключается к базе данных, за исключением того, что они ссылаются на свойства сущности. В этом случае DetailsView
элемент управления используется только для вставки строк, поэтому для режима по умолчанию задано значение Insert
.
Запустите страницу и добавьте нового учащегося.
После вставки нового учащегося ничего не произойдет, но если запустить Students.aspx, вы увидите новые сведения об учащемся.
Отображение данных в списке Drop-Down
На следующих шагах вы привязите элемент управления к набору DropDownList
сущностей с помощью EntityDataSource
элемента управления . В этой части учебника вы не будете много делать с этим списком. В последующих частях, однако, вы будете использовать список, чтобы позволить пользователям выбирать отдел для отображения курсов, связанных с отделом.
Создайте веб-страницу с именем Courses.aspx. В представлении источника добавьте заголовок в Content
элемент управления с именем Content2
:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Courses by Department</h2>
</asp:Content>
В режиме конструктора добавьте элемент EntityDataSource
управления на страницу, как и раньше, за исключением того, что на этот раз назовите его DepartmentsEntityDataSource
. Выберите Отделы в качестве значения EntitySetName и выберите только свойства DepartmentID и Name .
На вкладке Стандартныйпанели элементов перетащите DropDownList
элемент управления на страницу, назовите его DepartmentsDropDownList
, щелкните смарт-тег и выберите Выбрать источник данных , чтобы запустить мастер настройки источника данных.
На шаге Выбор источника данных выберите DepartmentsEntityDataSource в качестве источника данных, щелкните Обновить схему, а затем выберите Имя в качестве отображаемого поля данных и DepartmentID в качестве поля данных значения. Нажмите кнопку ОК.
Метод, используемый для привязки данных элемента управления с помощью Entity Framework, совпадает с другими ASP.NET элементами управления источником данных, за исключением того, что вы указываете сущности и свойства сущности.
Перейдите в исходное представление и добавьте "Выбрать отдел:" непосредственно перед элементом DropDownList
управления .
Select a department:
<asp:DropDownList ID="DropDownList1" runat="server"
DataSourceID="EntityDataSource1" DataTextField="Name"
DataValueField="DepartmentID">
</asp:DropDownList>
Напомним, что на этом этапе измените разметку EntityDataSource
для элемента управления, заменив атрибуты ConnectionString
и DefaultContainerName
атрибутом ContextTypeName="ContosoUniversity.DAL.SchoolEntities"
. Часто рекомендуется подождать, пока вы не создадите элемент управления с привязкой к данным, связанный с элементом управления источником данных, перед изменением EntityDataSource
разметки элемента управления, так как после внесения изменений конструктор не предоставит параметр Обновить схему в элементе управления с привязкой к данным.
Запустите страницу, и вы сможете выбрать отдел из раскрывающегося списка.
На этом мы завершаем введение в использование EntityDataSource
элемента управления . Работа с этим элементом управления обычно ничем не отличается от работы с другими ASP.NET элементами управления источником данных, за исключением того, что вы ссылаетесь на сущности и свойства вместо таблиц и столбцов. Единственным исключением является доступ к свойствам навигации. В следующем руководстве вы увидите, что синтаксис, используемый с EntityDataSource
элементом управления, также может отличаться от других элементов управления источником данных при фильтрации, группировке и заказе данных.