Простое приложение с использованием Entity Framework

108

Лучшим способом начать обучение Entity Framework будет создание простого примера. Мы будем использовать подход Model-First при котором сначала создается графическая модель данных EDMX, а затем создаются объекты в базе данных. Подход Model-First имеет преимущество - он позволяет абстрагироваться от работы с базой данных и кодом C#, и заниматься непосредственно вопросами моделирования.

В качестве тестового проекта мы используем шаблон ASP.NET Empty Web Application – пустое приложение ASP.NET. Мы создадим модель, необходимую для работы с базой данных на сервере SQL Server Express, который входит в состав Visual Studio, а затем используем эту модель для создания функционального приложения.

Использование мастера EDM для создания модели

Первым шагом является создание модели базы данных. Это можно выполнить несколькими способами, но самым простым является использование инструмента Entity Data Model Wizard, который сделает всю “грязную” работу за вас. Для этого следуйте показанным ниже инструкциям:

  1. Запустите Visual Studio 2012 (в примерах всех статей мы будем использовать версию Visual Studio 2012 в сочетании с Entity Framework 6).

  2. Создайте новый проект ASP.NET, выбрав в меню File --> New Project. После этого откроется диалоговое окно, в котором укажите шаблон приложения ASP.NET Empty Web Application. Назовите произвольно проект и нажмите кнопку OK.

    Создание нового проекта ASP.NET
  3. В окне Solution Explorer щелкните правой кнопкой мыши по имени проекта и выберите в контекстном меню пункт Add New Item. В открывшемся диалоговом окне выберите шаблон ADO.NET Entity Data Model, который находится в разделе Data, и щелкните по кнопке Add.

    Добавление сущностной модели данных EDM
  4. После этого откроется начальное окно мастера Entity Data Model Wizard, в котором можно выбрать подход для работы с Entity Framework. Выберите вариант Empty EF Designer Model который предполагает создание пустой модели EDMX и последующей генерации на ее основе объектов базы данных.

    Создание пустой модели с помощью Entity Data Model Wizard
  5. После этого нажмите кнопку Finish. Вы увидите что мастер Entity Data Model Wizard создаст пустую модель в вашем проекте:

    Пустая модель EDMX

В окне Solution Explorer вы можете видеть созданный файл Model1.edmx, в котором, как было показано в предыдущей статье, описываются рабочий, удаленный и связующий слои архитектуры Entity Framework на языках CSDL, SSDL и MDL, основанных на синтаксисе XML, но имеющих различную семантику.

Использование дизайнера EDM

После создания модели данных в приложении, на рабочую область дизайнера EDM (которая открывается автоматически для файлов EDMX) можно добавлять различные элементы из панели Toolbox, графически описывающие структуру данных модели. Например, вы можете добавить элемент Entity, создающий новую сущность:

Инструменты Entity Framework на панели Toolbox

В качестве примера, давайте добавим простую сущность, описывающую покупателя в интернет-магазине и содержащую простые поля:

Для это выполните следующие шаги:

  1. Перетащите элемент Entity с панели инструментов Toolbox на рабочую область дизайнера EDM. После этого вы увидите, что будет создан графический элемент в виде прямоугольника, содержащий пустой объект – это пустая сущность. Обратите внимание, что дизайнер автоматически добавляет свойство Id для вас. Это свойство однозначно идентифицирует конкретный элемент.

    Создание пустого объекта в дизайнере EDM
  2. Щелкните правой кнопкой мыши по имени созданного объекта Entity1, выберите в контекстном меню пункт Rename (Переименовать) и введите имя Customer.

  3. Щелкните правой кнопкой мыши по свойству Id, выберите в контекстном меню пункт Rename и введите имя CustomerId.

  4. Щелкните правой кнопкой мыши по имени объекта Customer, выберите в контекстном меню пункт Add New --> Scalar Property. Вы увидите, что дизайнер добавил новое поле в наш объект.

  5. Введите имя FirstName и нажмите клавишу Enter.

  6. Повторите шаги 4-5, чтобы добавить остальные поля к нашему объекту. В результате должен быть создан объект наподобие показанному на рисунке ниже:

    Наполнение сущностного объекта в дизайнере EDM
  7. Измените тип данных для поля Age на Int32. Для этого выделите это свойство в объекте сущности и в панели Properties выберите из раскрывающегося списка свойства Type вариант Int32. Если панель Properties не открыта в Visual Studio, то выполните команду меню View --> Properties Window.

  8. Добавьте еще один объект Entity – Order, который будет описывать заказы и определите связь между объектами Customer и Order с помощью элемента Association на панели Toolbox. Должна получиться модель, наподобие показанной на рисунке ниже:

    Структура созданной модели EDM

Обратите внимание, что цвет объекта сущности в окне дизайнера по умолчанию синий. В сложных моделях иногда бывает полезным окрашивать некоторые элементы в другой цвет, чтобы различать их. Для этого вы можете выделить нужный объект в окне дизайнера EDM и изменить его свойство Fill Color на панели Properties.

Связь модели с базой данных

К данному моменту мы создали простую модель, которую можем применить в нашем приложении, но мы не привязали ее к реальной базе данных. Чтобы убедиться в этом, щелкните правой кнопкой мыши по объекту Customer и выберите в контекстном меню пункт Validate. Visual Studio отобразит ошибку в окне ErrorList:

Error 11007: Entity type 'Customer' is not mapped.	

Итак, нам нужно связать созданную модель с физической базой данных. Т.к. базы данных еще не существует на SQL Server, ее можно будет сгенерировать из нашей модели с использованиям средств Visual Studio (это еще одна сторона процесса разработки с использованием Model-First – сначала мы создали модель, а затем, на ее основе создаем базу данных). Для этого выполните следующие шаги:

  1. Щелкните правой кнопкой мыши по объекту Customer в дизайнере EDM и выберите пункт Generate Database From Model (Создать базу данных из модели). Откроется диалоговое окно, показанное на рисунке ниже:

    Диалоговое окно Generate Database From Model
  2. Щелкните по кнопке New Connection (Новое подключение). Откроется диалоговое окно Choose Data Source (Выбор источника данных), выберите Microsoft SQL Server. В открывшемся окне Connection Properties (Свойства подключения) введите имя сервера к которому необходимо выполнить подключение и введите имя базы данных TestCustomer:

    Настройка подключения к базе данных

    Обратите внимание, что если в этом окне вы нажмете кнопку Test Connection, чтобы проверить работает ли подключение к базе данных, то вылезет ошибка подключения, т.к. базы данных TestCustomer еще не существует.

  3. Нажмите кнопку OK, вы увидите диалоговое окно, сообщающее вам что база данных не существует и Visual Studio требует разрешение на ее создание.

  4. Нажмите кнопку Yes, Visual Studio создаст новую базу данных. В данный момент эта база данных пуста, в ней отсутствуют таблицы, индексы, представления и другие объекты. После этого вы вернетесь в окно Generate Database From Model. Если на данном этапе возникли проблемы с подключением или авторизацией SQL Server, базу данных можно изначально создать с помощью SQL Management Studio, а затем повторить шаги 1-4, указав в окне Connection Properties имя уже имеющейся базы данных.

  5. Нажмите кнопку Next (Далее) в окне Generate Database From Model. Мастер создаст скрипт на языке DDL - Data Definition Language (используется синтаксис T-SQL), в котором происходит создание таблиц базы данных.

    Сгенерированный код DDL
  6. Нажмите кнопку Finish (Готово). Visual Studio создаст файл Model1.edmx.sql, содержащий SQL-инструкции с использованием семантики DDL.

  7. Выполните этот скрипт, нажав на кнопке Execute (имеет вид зеленого треугольника на панели инструментов) или выполнив команды меню SQL --> Transact SQL Editor --> Execute. Вы увидите диалоговое окно, в котором нужно выбрать подключение к серверу SQL Server, на котором выполнится данный скрипт:

    Диалоговое окно с настройками подключения
  8. Введите все необходимые учетные данные и нажмите Connect (Подключиться). Среда Visual Studio подключится к базе данных и выполнит сценарий SQL, который она создала. В этот момент, база данных готова к использованию.

Обратите внимание как Visual Studio облегчает вам жизнь – не нужно вручную работать с базами данных и придумывать SQL-код для создания таблиц, нужно сделать всего пару кликов в дизайнере EDM и настроить подключение при создании базы данных.

Работа с данными

Теперь у нас есть база данных, сгенерированная из модели EDMX и мы можем продемонстрировать работу Entity Framework на примере нашего приложения ASP.NET. Для этого выполните следующие шаги:

  1. На данном этапе в таблице CustomerSet базы данных TestCustomer отсутствуют какие-либо данные. Давайте исправим это. Откройте в Visual Studio окно обозревателя серверов Server Explorer с помощью команды View --> Server Explorer. Вы увидите подключение к базе данных Model1Container, как показано на рисунке ниже (это подключение было автоматически добавлено в окно Server Explorer при генерации базы данных):

    Подключение к созданной базе данных в окне Server Explorer
  2. Щелкните правой кнопкой мыши по имени таблицы CustomerSet и выберите в контекстном меню пункт New Query. Выполните следующий SQL-код, для вставки данных в таблицу:

    INSERT INTO CustomerSet VALUES 
        ('Василий', 'Фролов', 'Москва', 26), 
        ('Елена', 'Лебеденко', 'Москва', 32),
        ('Анна', 'Иванова', 'Санкт-Петербург', 20),
        ('Игорь', 'Соловьев', 'Казань', 56),
        ('Дмитрий', 'Волков', 'Санкт-Петербург', 28),
        ('Наталья', 'Вершинина', 'Москва', 31),
        ('Олег', 'Маменко', 'Волгоград', 34)
  3. Вставьте в проект новую веб-форму по имени Default.aspx. Для этого щелкните правой кнопкой мыши по имени проекта в окне Solution Explorer и выберите пункт Add New Item. В открывшемся диалоговом окне выберите шаблон Web Form. Измените разметку формы:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ProfessorWeb.EntityFramework.Default" %>
    
    <!DOCTYPE html>
    <html>
    <head runat="server">
        <title>professorweb.ru - Entity Framework 6</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:ListView ID="ListView1" runat="server" ItemType="ProfessorWeb.EntityFramework.Customer"
                 SelectMethod="GetCustomers" UpdateMethod="EditCustomer" DeleteMethod="DeleteCustomer"
                 InsertMethod="InsertCustomer" DataKeyNames="CustomerId">
                <LayoutTemplate>
                    <table>
                        <tr>
                            <th>ID</th>
                            <th>Имя</th>
                            <th>Фамилия</th>
                            <th>Город</th>
                            <th>Возраст</th>
                            <th></th>
                        </tr>
                        <tr id="itemPlaceholder" runat="server"></tr>
                    </table>
                </LayoutTemplate>
    
                <ItemTemplate>
                    <tr>
                        <td><%# Item.CustomerId %></td>
                        <td><%# Item.FirstName %></td>
                        <td><%# Item.LastName %></td>
                        <td><%# Item.City %></td>
                        <td><%# Item.Age %></td>
                        <td>
                            <asp:Button CommandName="Edit" runat="server" Text="Изменить" />
                            <asp:Button CommandName="Delete" runat="server" Text="Удалить" />
                        </td>
                    </tr>
                </ItemTemplate>
    
                <EditItemTemplate>
                    <tr>
                        <td><%# Item.CustomerId %></td>
                        <td><input id="firstName" runat="server" value="<%# BindItem.FirstName %>" /></td>
                        <td><input id="lastName" runat="server" value="<%# BindItem.LastName %>" /></td>
                        <td><input id="city" runat="server" value="<%# BindItem.City %>" /></td>
                        <td><input id="age" runat="server" value="<%# BindItem.Age %>" /></td>
                        <td>
                            <asp:Button CommandName="Update" runat="server" Text="Сохранить" />
                            <asp:Button CommandName="Delete" runat="server" Text="Отмена" />
                        </td>
                    </tr>
                </EditItemTemplate>
    
                <InsertItemTemplate>
                    <tr>
                        <td></td>
                        <td><input id="firstName" runat="server" value="<%# BindItem.FirstName %>" /></td>
                        <td><input id="lastName" runat="server" value="<%# BindItem.LastName %>" /></td>
                        <td><input id="city" runat="server" value="<%# BindItem.City %>" /></td>
                        <td><input id="age" runat="server" value="<%# BindItem.Age %>" /></td>
                        <td>
                            <asp:Button ID="Button1" CommandName="Insert" runat="server" Text="Вставить" />
                        </td>
                    </tr>
                </InsertItemTemplate>
            </asp:ListView>
        </form>
    
        <style>
            th, td { padding: 8px; }
            th { background: #28a4fa; color: white; font-weight: bold; }
            tr:nth-of-type(even) { background: #eee; }
            tr:nth-of-type(odd) { background: #fffbd6; }
        </style>
    </body>
    </html>

    В этом примере мы используем элемент управления ListView для отображения и редактирования данных. Теперь откройте файл отделенного кода веб-формы Default.aspx.cs и введите следующий код:

    using System;
    using System.Linq;
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.Web.UI.WebControls;
    
    namespace ProfessorWeb.EntityFramework
    {
        public partial class Default : System.Web.UI.Page
        {
            // В этом поле хранится информация о базе данных
            Model1Container dbContext;
    
            protected void Page_Load(object sender, EventArgs e)
            {
                dbContext = new Model1Container();
                ListView1.InsertItemPosition = InsertItemPosition.LastItem;
            }
            
            // ...
        }
    }

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

  4. Теперь мы можем использовать возможности Entity Framework, для того, чтобы реализовать методы чтения, удаления, изменения и вставки данных – их еще называют методами CRUD (create read update delete). Вставьте следующий код в файл Default.aspx.cs:

    using System;
    using System.Linq;
    using System.Data.Entity;
    using System.Collections.Generic;
    using System.Web.UI.WebControls;
    
    namespace ProfessorWeb.EntityFramework
    {
        public partial class Default : System.Web.UI.Page
        {
            // ...
    
            // Отобразить всех покупателей
            public IQueryable<Customer> GetCustomers()
            {
                // Используем LINQ-запрос для извлечения данных
                return dbContext.CustomerSet.AsQueryable<Customer>();
            }
    
            // Редактировать данные покупателя
            public void EditCustomer(int? customerId)
            {
                Customer customer = dbContext.CustomerSet
                    .Where(c => c.CustomerId == customerId).FirstOrDefault();
    
                if (customer != null && TryUpdateModel<Customer>(customer))
                {
                    // Обновить данные в БД с помощью Entity Framework
                    dbContext.Entry<Customer>(customer).State = EntityState.Modified;
                    dbContext.SaveChanges();
                }
            }
    
            // Удалить покупателя
            public void DeleteCustomer()
            {
                Customer customer = new Customer();
    
                if (TryUpdateModel<Customer>(customer))
                {
                    dbContext.Entry<Customer>(customer).State = EntityState.Deleted;
                    dbContext.SaveChanges();
                }
            }
    
            // Вставить нового покупателя
            public void InsertCustomer()
            {
                Customer customer = new Customer();
    
                if (TryUpdateModel<Customer>(customer))
                {
                    dbContext.Entry<Customer>(customer).State = EntityState.Added;
                    dbContext.SaveChanges();
                }
            }
        }
    }

    Обратите внимание, что свойство CustomerSet класса Model1Container представляет собой таблицу CustomerSet в базе данных (приставка Set была автоматически добавлена при генерации базы данных). Фактически это свойство возвращает коллекцию всех покупателей. Приведение значения этого свойства к типу IQueryable в методе GetCustomers() является одной из оптимизаций запросов Entity Framework, известной как ленивая загрузка (lazy loading), позволяющая выполнять отложенный LINQ-запрос (отложенное выполнение запросов является главным отличием типов IEnumerable и IQueryable).

  5. Запустите проект и проверьте функциональность созданной веб-формы:

    Результат

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

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

Кроме того, изменения, сделанные разработчиком в модели EDMX автоматически отображаются на базу данных и наоборот, изменения сделанные в базе данных, например администратором, отображаются на модели EDMX (этот момент мы не рассмотрели выше, в дизайнере EDM вы можете щелкнуть правой кнопкой мыши по нужному объекту и выбрать в контекстном меню пункт Update Model from Database для обновления модели из базы данных). Эти возможности появляются за счет автоматизации процесса отображения данных на объектную модель приложения (с помощью средств Visual Studio).

Пройди тесты
Лучший чат для C# программистов