5 мин

ADO.NET Entity Framework: практическое введение

Практическое введение в ADO.NET Entity Framework — от создания модели данных до выполнения базовых операций CRUD в ASP.NET.

Тем, кто пишет запросы в коде страницы, посвящается…

Приветствую всех!

На Хабре есть немного информации о том, что в следующей версии Visual Studio 2008 будет ADO.NET Entity Framework. (Открою секрет, эта версия уже появилась.) Эта разработка представляет собой универсальный фреймворк, который позволяет создавать даталогику вашего проекта в пару кликов мыши.

До сих пор, работая с даталогикой, я сталкивался с двумя видами проектов. Первые были созданы на небезызвестном фреймворке NHibernate, другие реализовывали даталогику силами программистов. Я уже три года занимаюсь написанием и разработкой различных систем и всё это время разрабатывал логику работы с данными исключительно ручками.

И вот, на днях, после того как я поставил новую винду, я скачал Visual Studio Web Developer Express и с радостью обнаружил в комплекте поставки ADO.NET Entity Framework. Через некоторое время зарегистрировал домен, создал простенький сайт и начал тренировать свои силы в написании программ под этот фреймворк.

Начало работы

Я был немного неприятно удивлён тем, что большинство статей о ADO.NET EF были узконаправленными. Невозможно было найти полной информации, от начала до конца, о том, как правильно настроить базу, создать сущности и произвести базовые действия над этими сущностями. Большинство статей раскрывают лишь одну из этих тем. Что ж, обучаясь, я решил поделиться опытом с тобой, %username%. В то же время, используя мой код, вы не сможете поднять систему работы с бизнес-процессами, но всё-таки поймёте, с какой стороны к чему подходить.

Для начала необходимо создать простой Web-проект с базой данных. К базе данных тоже неплохо было бы подключиться сразу через Database Explorer — просто потом будет удобнее.

После этого в проект надо добавить новый элемент — ADO.NET Entity Data Model. Системе надо будет указать строку для соединения с базой, а также указать, откуда возьмётся первая модель ADO.NET EF. В своей БД я уже имею две очень простых таблицы — Post и User, поэтому, не мудрствуя лукаво, я заставил систему создать модель на основе моей БД.

Сгенерированный код

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

namespace DataBaseCore
{
    /// <summary>
    /// There are no comments for DbModel in the schema.
    /// </summary>
    public partial class DbModel : global::System.Data.Objects.ObjectContext
    {
        /// <summary>
        /// Initializes a new DbModel object using the connection string
        /// found in the 'DbModel' section of the application configuration file.
        /// </summary>
        public DbModel() :
            base("name=DbModel", "DbModel")
        {
            this.OnContextCreated();
        }

        /* Урезал за ненадобностью */

        [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(
            NamespaceName="DataBaseCore", Name="Post")]
        [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)]
        [global::System.Serializable()]
        public partial class Post : global::System.Data.Objects.DataClasses.EntityObject
        {
            /// <summary>
            /// Create a new Post object.
            /// </summary>
            /// <param name="id">Initial value of Id.</param>
            public static Post CreatePost(int id)
            {
                Post post = new Post();
                post.Id = id;
                return post;
            }
        }
    }
}

Намётанный глаз специалиста по работе с даталогикой показал наличие достаточно простого и изящного класса, который позволил работать как с постами в системе, так и с пользователями.

Entity Data Source

Ну что ж, код у нас уже есть, осталось только его начать использовать. И тут нам открываются все прелести и возможности ASP.NET. Среди немалого количества источников данных на странице я увидел Entity Data Source, который с удовольствием предоставляет данные по запросу из нашего класса. Перетаскиваем его на форму, запускаем мастер настройки и быстренько цепляем датасорс на нашу таблицу постов. Несомненно, намного приятнее стало выглядеть описание датасорса в ASPX-коде:

<asp:EntityDataSource ID="dsPosts" runat="server"
    ConnectionString="name=DbModel"
    DefaultContainerName="DbModel" EntitySetName="Post">
</asp:EntityDataSource>

Можно сказать — блещет изяществом.

После появления на форме провайдера данных нужен и потребитель. Не умничая, я добавил простенький код, который просто отображает все посты последовательно:

<asp:Repeater runat="server" ID="repPosts" DataSourceID="dsPosts">
    <HeaderTemplate>
    </HeaderTemplate>
    <ItemTemplate>
        <div>
            <h3>
                <asp:Label ID="lblHeader" runat="server"
                    Text='<%# Eval("Header") %>'></asp:Label>
            </h3>
            <p>
                <asp:Label ID="lblText" runat="server"
                    Text='<%# Helpers.TypographText(Eval("Text").ToString()) %>'></asp:Label>
            </p>
        </div>
    </ItemTemplate>
</asp:Repeater>

Пишем код

И вот тут заканчивается самая простая часть моего повествования. До сих пор всё, что было сделано, можно повторить при помощи мыши. Это было достаточно просто. Мы только что создали объектно-ориентированное представление БД и, используя это представление, начали выводить данные из базы на страницу. При этом мы ни разу не написали ни одного запроса, не получали данные из базы напрямую и так далее.

Но что же выводить пользователю, если у нас нет ничего в БД? Нехорошо. Надо написать форму заполнения базы. Теперь мы бросим мышепрограммирование и займёмся написанием кода.

Я сделал два самых базовых действия для работы с постами в системе — это добавление и удаление. Сделать редактирование по аналогии с этим кодом не составит труда ни для кого:

namespace DBW
{
    public class Post
    {
        public Post()
        {
        }

        public static void New(String PostText, String PostHeader, Int32 UserId)
        {
            DataBaseCore.DbModel m = new DataBaseCore.DbModel();
            DataBaseCore.Post p = new DataBaseCore.Post();
            p.Header = PostHeader;
            p.Text = Helpers.TypographText(PostText);
            p.PublishDate = DateTime.Now;
            p.User = (from usr in m.User
                      where usr.Id == UserId
                      select usr).First();
            m.AddToPost(p);
            m.SaveChanges();
        }

        public static void Delete(Int32 PostId)
        {
            DataBaseCore.DbModel m = new DataBaseCore.DbModel();
            DataBaseCore.Post p = new DataBaseCore.Post();
            p = (from pst in m.Post
                 where pst.Id == PostId
                 select pst).First();
            m.DeleteObject(p);
            m.SaveChanges();
        }
    }
}

Нюансы

Казалось бы, всё просто, и да, это так. Но есть пара нюансов.

Во-первых — это LINQ. Без него в ADO.NET EF никуда. Так что не стоит отлынивать и вообще забивать на SQL или LINQ — писать запросы всё равно придётся.

Во-вторых — этот код автоматически генерируется фреймворком, поэтому особого удобства в некоторых моментах ожидать не придётся, и всегда надо быть готовым изменить уже созданный студией код. Например, в строке 16 было бы удобнее использовать не объект типа пользователь, который мне пришлось выбирать из БД, а сразу передавать значение идентификатора пользователя. Так было бы удобнее для этого кода, но это не универсально. Поэтому код нуждается в доработке и переосмыслении. Возможно, просто надо передавать не идентификатор пользователя, а объект типа пользователь.

Что дальше?

Дальше я буду продолжать писать проект, углубляясь в дебри ADO.NET Entity Framework, и буду с удовольствием делиться своими изысканиями. Соответственно, будут новые статьи с более серьёзными и глубокими данными.

UPD. Тема очень обширная. Здесь не раскрыто и процента возможностей, но продолжение будет.

Читать дальше

Похожие посты