Asp.net mvc framework
Шрифт:
protected void DoSomethingWithCustomer(Guid someCustomerId)
{
using (SqlConnection conn = new SqlConnection(@"
Data Source=localhost;
Initial Catalog=BookMVC; Integrated Security=True"))
{
conn.Open;
SqlCommand cmd = new SqlCommand(@"
SELECT * FROM Customers
WHERE customerId = @customerId", conn);
cmd.Parameters.Add(
new SqlParameter("customerId", someCustomerId));
SqlDataReader reader = cmd.ExecuteReader;
if (reader.Read)
{
SqlCommand updateCmd = new SqlCommand(@"
UPDATE Customers SET name = @name
WHERE customerId = @customerId", conn);
updateCmd.Parameters.Add(
new SqlParameter(''name", "Заказчик 1"));
updateCmd.Parameters .Add(
new SqlParameter("customerId", someCustomerId));
updateCmd.ExecuteNonQuery;
}
reader.Close;
}
}
Простота LINQ
Трудно сказать, было ли это ответным шагом или так и планировалось, но Microsoft спустя некоторое время анонсировала новую разработку, "честную" ORM, Entity Framework.
Entity Framework
Выход финальной версии Entity Framework произошел одновременно с выходом Service Pack 1 для Visual Studio 2008 и Service Pack 1 для .NET Framework 3.5 в августе 2008 года. Ранее доступный для бета-тестирования как отдельный продукт, с выходом обновлений, Entity Framework стал частью .NET Framework и Visual Studio, которая предложила средства для визуального моделирования мэппинга базы данных.
Entity Framework — это "настоящая" ORM, в которой присутствуют все те вещи, которых не хватало в LINQ для SQL. Здесь и поддержка комплексных типов, наследования типов и возможность создания моделей для любой БД (через специальный провайдер). Entity Framework описывается специальным файлом в формате EDM, который включает в себя трехуровневую архитектуру: концептуальный слой, схему источника данных и слой мэппинга, что представляет собой значительно более гибкое решение, чем одноуровневый вариант DBML-файлов LINQ для SQL. Работа с Entity Framework так же базируется на механизме LINQ, называемом LINQ для сущностей, который во многом схож с LINQ для SQL. Вместе со значительно улучшенным функционалом Entity Framework стала более требовательной к разработчику. Так, в ней пропали некоторые механизмы LINQ для SQL, например, так называемый механизм ленивой загрузки (Lazy Loading) данных, когда данные автоматически подгружаются по мере надобности.
Далее приведен пример этого случая:
MyDatabaseDataContext db = new MyDatabaseDataContext;
var orders = db.Customers.First.Orders;
В случае с LINQ для SQL этот код вернет данные в виде набора заказов первого заказчика в наборе данных, тогда как Entity Framework данных не вернет. Связано это с тем, что в первом случае работает механизм Lazy Loading, который подгружает данные заказов при обращении к ним. Тогда как в Entity Framework разработчик должен сам определить код, который подгрузит данные. Для того чтобы получить данные в Entity Framework, необходимо прямо их затребовать:
MyDatabaseDataContext db = new MyDatabaseDataContext; var customer = db.Customers.First; customer.Orders.Load; // загружаем
данные var orders = customer.Orders;Этот пример наглядно демонстрирует разнонаправленность двух механизмов LINQ для SQL и Entity Framework, которая позволяет им существовать параллельно: если вам нужно отображение баз данных SQL Server на классы вашей бизнес-логики, чтобы все "просто работало", необходима скоростная разработка, и к гибкости ORM не предъявляются повышенные требования, то LINQ для SQL вполне может стать тем инструментом, который полностью удовлетворит ваши потребности. В случае же, когда к структуре модели данных и возможностям ORM предъявляются серьезные требования, вроде потенциальной поддержки разнообразных источников данных, то среди двух описанных ранее технологий Entity Framework — это то, что вам нужно.
Принципы построения слоя доступа к данным
Грамотно построенное приложение состоит из множества слабосвязанных, легкозаменяемых частей. В этом смысле при построении слоя доступа к данным (рис. 3.4) можно определить следующие принципы:
? для доступа к модели данных необходимо использовать механизм ORM, который предпочтительнее всего взять со стороны, но не реализовывать своими силами;
? интеграция ORM в систему должна быть слабосвязанной, так, чтобы существовала безболезненная возможность перейти на другой вариант ORM;
? вместе с моделью данных, которую предоставит ORM, необходимо реализовать хранилища и сервисы, которые будут предоставлять доступ к необходимым наборам данных и реализовывать добавление, видоизменение и удаление данных. Реализация слабосвязанных сервисов и хранилищ позволит скрыть подробности реализации доступа к данным, предоставляемых ORM, что даст большую гибкость слою доступа к данным и позволит исключить жесткую привязку, например, к LINQ-запросам для работы с ORM.
Что дает такая схема, и зачем нужна дополнительная прослойка между ORM и бизнес-логикой приложения:
? внедрение хранилища для типовых запросов, например, получения записи по идентификатору или получения всех заявок заказчика, позволит, с одной стороны, унифицировать получение таких данных, а с другой, сделает связь с ORM менее жесткой;
? внедрение сервисов похоже на внедрение хранилищ, только реализующих логику управления данными. Например, хорошей практикой является определение сервиса, который добавляет, изменяет либо удаляет данные. Обращаясь к такому сервису, ваш код не будет зависеть от реализации функций, существующей ORM и даже базы данных;
? внедрение такого рода инъекций кода отделяет бизнес-логику от ORM и уменьшает зависимость между ними, что позволит в дальнейшем без особых трудов использовать другой ORM, переписав для этого только хранилище и сервисы. В случае же прямой связи бизнес-логики с ORM, безболезненной замены ORM провести не удастся, т. к. придется инспектировать и переписывать весь написанный код.
Возможность замены источника данных
Для более наглядного примера потребности в промежуточном коде и необходимости предусматривать возможные изменения в работе с ORM приведем случай из практики одного из авторов книги. Компания, в которой он работал, разрабатывала крупный проект, работающий с использованием SQL Server 2000. После нескольких лет разработки и поддержки, заказчик пожелал сменить SQL Server на другую СУБД. В связи с тем, что код проекта был жестко завязан на особенностях SQL Server, такой переход стоил больших усилий всего персонала компании.
В то время еще не существовало LINQ для SQL, но даже если бы компания использовала этот ORM, ей все равно пришлось бы переписывать подавляющую часть кода работы с данными в связи с тем, что LINQ для SQL не поддерживает ничего, кроме SQL Server.
В случае же, если бы существовала инъекция кода в виде хранилищ и сервисов, необходимо было бы реализовать только их новый вариант без затрагивания любого другого кода. Излишне говорить, что затраченное на это время было бы значительно меньшим по сравнению с тем, сколько было потрачено на самом деле.