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. Тема очень обширная. Здесь не раскрыто и процента возможностей, но продолжение будет.
Читать дальше
Похожие посты
Наследование в ADO.NET Entity Framework
Практический разбор двух типов наследования в ADO.NET Entity Framework: Table per Type и Table per Hierarchy — с типичными ошибками и их решениями.
.NET Interop на примере работы с сокетами
Как скрестить ежа с ужом: используем P/Invoke и DllImport для работы с нативными Windows Sockets из .NET-приложения.
Код всегда ничего не стоил
Сорок лет мы делали вид, что софт — это товар. SaaS сдвинул цену на сервис. ИИ сдвинул её ниже нуля. Артефакт бесплатен. Платят теперь за понимание, какой именно код стоит писать.