412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Гайдар Магдануров » Asp.net mvc framework » Текст книги (страница 3)
Asp.net mvc framework
  • Текст добавлен: 8 июля 2026, 17:38

Текст книги "Asp.net mvc framework"


Автор книги: Гайдар Магдануров



сообщить о нарушении

Текущая страница: 3 (всего у книги 17 страниц)

После этого в MVC-приложение можно добавить стандартную ASPX-страницу, например WebForm1.aspx, код которой приведен в листинге 2.8, и для этой страницы будет обеспечена полноценная функциональность WebForms, что подтверждает рис. 2.4.

Листинг 2.8. Страница WebForml.aspx

<%@ Page Language="C#" AutoEventWireup="true"

      CodeBehind="WebForm1.aspx.cs"

      Inherits="MvcWebFormsCompositeApp.WebForm1" %>

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

 

   

      ConnectionString="<%$ ConnectionStrings:ConnectionString %>"

      SelectCommand="SELECT * FROM [Persons]">

   

   

   

         AutoGenerateColumns="False" DataKeyNames="PersonId"

         DataSourceID="SqlDataSource1">

     

        

             HeaderText="PersonId"

             InsertVisible="False" ReadOnly="True"

             SortExpression="PersonId" />

       

             HeaderText="LastName" SortExpression="LastName" />

        

             HeaderText="FirstName" SortExpression="FirstName" />

      

   

 

Использование MVC Framework в существующих решениях WebForms

Рассмотрим сценарий расширения существующего WebForms-приложения с использованием MVC Framework. Для этого нужно выполнить несколько простых шагов:

1. Установить в свойствах веб-приложения версию .NET Framework 3.5, поскольку если приложение WebForms было разработано для версии .NET Framework 2.0, то MVC Framework для нее не поддерживается.

2. Добавить ссылки на сборки System.Web.Mvc и System.Web.Routing.

3. Зарегистрировать в файле web.config необходимые для функционирования MVC-приложения обработчики в разделе system.web/httpModules (листинг 2.9) и system/webServer/modules и system/webServer/handlers (листинг 2.10). Необходимые изменения выделены полужирным. Кроме того, поскольку в листингах 2.9 и 2.10 сборки указываются без описания версий, необходимо в директорию bin веб-приложения скопировать файлы System.Web.Mvc.dll и System.Web.Routing.dll. Либо указать полные имена сборок, посмотрев описания в тестовом MVC-приложении, которое стоит создать по такому случаю.

4. Зарегистрировать пространства имен, которые будут использовать представления (листинг 2.11).

5. Создать таблицу маршрутизации в файле global.asax (листинг 2.12).

6. Создать директорию /Controllers, разместить в ней контроллеры.

7. Создать директорию /Views и разместить в ней дерево представлений, отвечающее контроллерам и их действиям (рис. 2.5).

Листинг 2.9. Регистрация модуля MVC Framework в web.config

 

   

      type=" System.Web.Routing.UrlRoutingModule,

      System.Web.Routing" />

   

      type="System.Web.Handlers.ScriptModule,

      System.Web.Extensions"/>

 

Листинг 2.10. Регистрация модулей и обработчиков MVC Framework в web.config

 

 

   

      type="System.Web.Handlers.ScriptModule,

      System.Web.Extensions"/>

     

 

 

   

      path="*.asmx" preCondition="integratedMode"

      type="System.Web.Script.Services.ScriptHandlerFactory,

      System.Web.Extensions"/>

   

      path="*_AppService.axd" preCondition="integratedMode"

      type="System.Web.Script.Services.ScriptHandlerFactory,

      System.Web.Extensions"/>

   

      verb="GET,HEAD" path="ScriptResource.axd"

      type="System.Web.Handlers.ScriptResourceHandler,

      System.Web.Extensions" />

   

      path=" *.mvc" type=" System.Web.Mvc.MvcHttpHandler,

      System.Web.Mvc"/>

   

      verb="*" path="UrlRouting.axd"

      type="System.Web.HttpForbiddenHandler, System.Web" />

 

Листинг 2.11. Регистрация пространств имен в файле web.config

 

   

   

   

   

   

   

  

Листинг 2.12. Таблица маршрутизации в файле Global.asax

public static void RegisterRoutes(RouteCollection routes)

{

  routes.IgnoreRoute(«{resource}.axd/{*pathInfo}») ;

  routes.IgnoreRoute(«{resource}.aspx/{*pathInfo}»);

  routes.MapRoute(«Default», «{controller}/{action}/{id}»,

    new { controller = «Home», action = «Index», id = "" });

}

protected void Application_Start()

{

  RegisterRoutes(RouteTable.Routes);

}

Рис. 2.5. Структура WebForms-приложения после добавления MVC-компонентов

После того как все необходимые шаги выполнены, можно продолжать пользоваться WebForms-приложением, а также использовать только что добавленные контроллер и представление, например, создав контроллер Home (листинг 2.13) и представление Index (листинг 2.14), можно получить при обращении по пути /Home/Index результат, представленный на рис. 2.6.

Листинг 2.13. Файл HomeController.cs

using System.Web.Mvc;

namespace WebFormsMvcInterop.Controllers {

  public class HomeController : Controller {

    public ActionResult Index()

    {

      return View();

    }

  }

}

Листинг 2.14. Файл Index.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

  Hello from MVC

Заключение

В этой главе мы рассмотрели достоинства и недостатки MVC Framework в сравнении с WebForms, а также возможности совместного использования этих технологий в рамках одного проекта. Пожалуй, нужно отметить, что не стоит смешивать эти технологии без необходимости, поскольку при совмещении WebForms и MVC Framework вы получаете все их недостатки, не всегда имея возможность полностью реализовать достоинства.

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

ГЛАВА 3

Модель и доступ к данным


Согласно паттерну проектирования MVC основное назначение модели – это определение объекта приложения, представлением которого является вид (View). Модель и вид отделены друг от друга и взаимодействуют только в виде оповещений: изменившись, модель оповещает вид, который, согласно новым данным, изменяет свое состояние. Со своей стороны, вид обращается к модели для получения актуальных данных для отображения.

Структура этой главы построена так, что мы начнем рассмотрение построения доступа к данным с обзора механизма Object Relation Mapping, его истории, развития и того, какие механизмы ORM присутствуют в .NET. Мы рассмотрим технологию LINQ, LINQ для SQL, Entity Framework. После этого на простом примере разберем принцип организации эффективного доступа к данным в проектах ASP.NET MVC. В конце главы вас ждет раздел, в котором описаны наиболее популярные механизмы доступа к данным.

Задача получения доступа к данным из кода программы достаточно неординарна по своей природе. С одной стороны, нам хотелось бы иметь возможность оперировать сущностями данных, например, при наличии сущности "Заказчики" (таблица Customers), мы бы хотели иметь в коде возможность оперировать списками заказчиков, иметь возможность добавлять, удалять и изменять данные заказчиков. С другой стороны, мы бы не хотели, чтобы происходило смешивание кода бизнес-логики с такими данными, как строки SQL-запросов, что может привести к самым плачевным последствиям: от нечитабельности кода до непонятных и трудно диагностируемых ошибок или дыр в безопасности в виде SQL-инъекций. Чтобы избежать этого, мы хотели бы отказаться от написания запросов к нашему источнику данных на свойственном базе данных языке (например, построение строк SQL-запросов или разбор XML-файлов), внедрив некую прослойку между данными и операциями над ними. Такой прослойкой, которая с одной стороны предоставит нам полный контроль над данными, а с другой, позволит оперировать над ними в нужном нам стиле, становится ORM.

ORM – это аббревиатура от Object Relation Mapping или, по-русски, объектно-реляционная проекция. Очень легко объяснить сущность ORM: это механизм, который отображает на объекты объектно-ориентированного языка программирования сущности источника данных. Таким образом, одна запись таблицы Customers реляционной СУБД отображается в класс Customer в вашем коде (рис. 3.1).

Рис. 3.1. Отображение сущности базы данных в класс на языке C#

Написание ORM – дело несложное, вполне возможно сделать свой вариант для конкретных задач. Но написание ORM имеет и свои отрицательные стороны. Минусы у собственноручно разработанного ORM следующие:

□ высокий порог вхождения для новичка, тогда как использование распространенного стороннего ORM предполагает большую вероятность того, что новичок знаком с ним;

□ необходимость поддерживать код. Если сторонние ORM разрабатываются специальными командами разработчиков, постоянно совершенствуются, модернизируются и исправляются, то самописный код, конечно же, придется сопровождать вам самим. И, в зависимости от компетенции и подхода, собственный код ORM может во многом проигрывать сторонним решениям в плане надежности или производительности.

Эти минусы в реальной жизни почти всегда перевешивают выгоду от собственного контроля над кодом ORM и заточенности под какие-то свои нужды.

Поэтому сторонние универсальные ORM получили такое широкое распространение.

ORM – не настолько старая технология, как можно было бы подумать. Трудно сказать достоверно, но, возможно, самым первым ORM, получившим широкое распространение, был продукт TopLink для языка программирования Smalltalk. Тогда этот проект принадлежал компании The Object People, название которой и легло в основу названия продукта. TopLink для SmallTalk вышел в 1994 году, а уже в 1996 году появилась версия для Java, которая называлась соответственно TopLink для Java. На сегодняшний момент, после серии покупок, TopLink принадлежит компании Oracle, которая продолжает выпускать его для Java-разработчиков.

Следующими за TopLink в очередности ORM-продуктов можно считать Java Database Objects и Entity Beans, первые версии которых появились в конце 90-х—начале 2000-х годов. Как нетрудно заметить, на ранних стадиях ORM как технология развивалась в основном в Java-среде.

Но самой значимой вехой в истории ORM можно считать появление продукта Hibernate, который был разработан сообществом Java-программистов под руководством Гэвина Кинга (Gavin King). Позднее компания JBoss наняла ведущих разработчиков Hibernate для развития и поддержки проекта. Еще позднее JBoss стала частью компании Red Hat, которая до сих пор поддерживает проект Hibernate.

С ростом популярности .NET-платформы самая известная ORM-библиотека была портирована и на .NET, получив название NHibernate. Последняя версия NHibernate 2.0.1 вышла в конце 2008 года, на момент написания книги известно, что версия 3.0 проекта находится в разработке и будет использовать .NET 3.5-функционал, в том числе и LINQ, о котором речь пойдет далее.

На данный момент ORM-библиотеки реализованы для многих популярных платформ и языков программирования: С++, Delphi, PHP, Python, Ruby, Perl, в чем можно убедиться, если посмотреть статью про ORM в Wikipedia. Для каждого из языков на текущий момент существует несколько, если не сказать множество, разнообразных ORM. Так, только для одной платформы .NET существует около тридцати разнообразных ORM-библиотек, что наглядно иллюстрирует современный тренд к повсеместному использованию ORM в разработке проектов любой сложности.

Компания Microsoft также представила свои решения в области ORM, ими стали LINQ для SQL и Entity Framework. Работа с обеими библиотеками производится с помощью интегрированного языка запросов LINQ, о котором и пойдет речь далее.

Технология LINQ

Технология LINQ или Language Integrated Query, что можно перевести как «интегрированные в язык запросы», появилась на свет вместе с выходом .NET Framework 3.5 в ноябре 2007 года. Как и многие другие наработки Microsoft, LINQ первоначально прошла путь экспериментального проекта под названием С(омега).

Суть LINQ проста – дать возможность разработчикам единообразно работать с коллекциями и наборами данных из разных источников, будь то: базы данных, XML-файлы, коллекции в языке программирования. Для этих целей реализуется определенный LINQ-провайдер, вроде встроенных в .NET Framework LINQ для XML, LINQ для SQL, LINQ для объектов, LINQ для сущностей. Решению этой задачи поспособствовали добавленные в .NET Framework 3.5 языковые расширения. Например, в C# появились анонимные методы и лямбда-выражения, которые интенсивно используются в LINQ.

Рассмотрим простейший пример LINQ-выражения:

List a = new List(3);

a.Add(3);

a.Add(12) ;

a.Add(-l);

List positive = a.Where(x => x >= 0).Select(x => x).ToList();

В данном примере создается коллекция типа List (список целочисленных значений) и заполняется тремя значениями. Последняя строчка – это и есть работа LINQ-механизма, который, используя набор методов LINQ для объектов, позволяет нам выбрать все положительные значения (согласно условию лямбда-выражения) в другой список. Для сравнения посмотрите на фрагмент кода, который выполняет те же действия, но без использования LINQ:

List a = new List(3);

a.Add(3) ;

a.Add(12) ;

a.Add(-1);

List positive = new List();

foreach (int item in a)

{

  if (item >= 0)

  positive.Add(item) ;

}

То, для чего обычно требовалось несколько строк кода, циклы и условия, теперь можно записать одним выражением в одной строке. Это и есть суть LINQ. В языке C# существует альтернативный вариант записи LINQ-выражений, который выглядит так:

List positive = (

                from x in a

                where x >= 0

                select x

                ).ToList ();

Как можно заметить, этот вариант во многом похож на синтаксис SQL-запросов. Что и не удивительно, поскольку этот вариант разрабатывался с учетом потребности в написании таких запросов архитекторами SQL-баз данных и специалистов, привыкших к подобному синтаксису. В своих проектах вы можете использовать любой из вариантов либо смешивать их друг с другом. Как показывает практика, каждый из них предпочтителен в разных конкретных случаях.

Рассмотренный пример задействует в себе механизм LINQ для объектов, который позволяет оперировать с коллекциями и другими стандартными наборами данных. Но кроме него огромное значение при работе с данными играют два других LINQ-провайдера: LINQ для SQL и LINQ для сущностей, которые призваны поддержать работу с двумя отдельными друг от друга ORM: LINQ для SQL и Entity Framework.

LINQ для SQL

LINQ для SQL является встроенным в .NET Framework механизмом, что отличает его от появившегося немного позднее Entity Framework. Благодаря этой встроенной поддержке и удобным инструментам мэппинга базы данных, LINQ для SQL получил очень широкое распространение. Способствовало этому также простота работы с ORM и низкий порог вхождения для любого разработчика. Кроме того, для создания ORM-базы данных с помощью LINQ для SQL не требуется писать ни строчки кода (хотя такая возможность и присутствует). В помощь разработчикам был предложен мастер создания модели данных, который формирует особый DBML-файл и файл с необходимыми для мэппинга классами. От разработчика требуется только указать подключение к БД и выбрать необходимые таблицы, все остальное мастер берет на себя (рис. 3.2 и 3.3).

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

protected void DoSomethingWithCustomer(Guid someCustomerld)

{

  MyDatabaseDataContext db = new MyDatabaseDataContext();

  var customer = db.Customers.SingleOrDefault(

              x => x.customerId == someCustomerId);

  if (customer != null)

  {

    customer.name = "Заказчик 1";

    db.SubmitChanges();

  }

}

Рис. 3.2. Окно создания модели LINQ для SQL

Рис. 3.3. Добавление в LINQ для SQL таблицы Customer

Здесь создается контекст базы данных MyDatabaseDataContext, ищется пользователь с определенным идентификатором someCustomerid, если он найден, у него меняется наименование на Заказчик 1 и изменения вносятся в базу данных вызовом метода Submitchanges. Такой же код, но с использованием механизма ADO.NET, приведен в следующем фрагменте. Вы сами можете сравнить оба способа по требуемому количеству кода и простоте:

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 для SQL послужила его широкой распространенности. Но вместе с тем, в LINQ для SQL существуют и свои минусы. Во-первых, не так редки ситуации, когда неверно или некорректно построенное разработчиком LINQ-выражение приводит к потерям в производительности, к выборке лишних данных, к расходу памяти. Кроме того, в LINQ для SQL отсутствуют такие механизмы, как прозрачный мэппинг таблиц, связанных друг с другом через промежуточную таблицу отношением «многие-ко-многим». Многие разработчики на веб-сайтах, блогах и других сетевых ресурсах критиковали LINQ для SQL как ORM Framework за недостатки, как в производительности, так и в функциональном плане. Некоторые из них утверждают, что LINQ для SQL вовсе нельзя считать полноценным ORM Framework, справедливо замечая, что в нем нет возможности, например, создавать комплексные типы или производить наследование типов. По сути своей LINQ для SQL скорее представляет собой строго типизированное представление базы данных SQL Server, чем полноценный механизм ORM. Еще один недостаток LINQ для SQL заключается в его привязке к SQL Server, как к единственно возможному источнику данных. Безусловно, для ORM это ограничение является огромным недостатком, поскольку на рынке представлено свыше десятка разнообразных баз данных.

Трудно сказать, было ли это ответным шагом или так и планировалось, но 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.

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

Реализация слоя данных

Создадим простейший слой для работы с базой данных, который отвечал бы всем нашим требованиям. Для начала возьмем простую структуру базы данных (рис. 3.5).

Рис. 3.5. Структура базы данных

У нас есть три таблицы: заказчики, заказы и товары. Каждая из таблиц содержит набор свойственных ей полей, так в таблице Products (товары) есть поле isAvailible, которое показывает, доступен ли товар в настоящее время. У таблицы Orders (заказы) есть поля count – количество товара в штуках и orderDateTime – дата и время оформления заказа. Таблица Customers (заказчики) содержит информацию о заказчике.

Для реализации хранилищ и сервисов нам необходимы интерфейсы данных, определим их так, как показано в листинге 3.1.

Листинг 3.1. Интерфейсы данных

public interface ICustomer {

  Guid CustomerId { set; get; }

  string Name { set; get; }

  string Phone { set; get; }

  string Address { set; get; }

}

public interface IOrder {

  Guid OrderId { set; get; }

  Guid CustomerId { set; get; }

  Guid ProductId { set; get; }

  int Count { set; get; }

  DateTime OrderDateTime { set; get; }

}

public interface IProduct {

  Guid ProductId { set; get; }

  string Name { set; get; }

  bool IsAvailible { set; get; }

  bool Cost { set; get; }

}

Воспользуемся мастером создания модели LINQ для SQL, чтобы сгенерировать классы для работы с базой данных. Посмотрим на сгенерированный код для таблицы Customers (приведен только фрагмент кода):

public partial class Customer : INotifyPropertyChanging,

                                INotifyPropertyChanged

{

  private System.Guid _customerId;

  private string _name;

  private string _address;

  private string _phone;

  private EntitySet _Orders;

  public Customer()

  {

    // код

  }

  [Column(Storage="_customerId",

    DbType="UniqueIdentifier NOT NULL",

    IsPrimaryKey=true)] public System.Guid customerId {

      get { return this._customerId; }

      set { // код }

    }

  [Column(Storage="_name",

    DbType="NVarChar(250) NOT NULL", CanBeNull=false)]

  public string name {

    get { return this._name; }

    set { // код }

  }

  [Column(Storage="_address",

    DbType="NVarChar(1024) NOT NULL",

    CanBeNull=false)]

  public string address {

    get { return this._address; }

    set { // код }

  }

  [Column(Storage="_phone", DbType="NVarChar(250)")]

  public string phone {

    get { return this._phone; }

    set { // код }

  }

  [Association(Name="Customer_Order",

    Storage="_Orders", ThisKey="customerId",

    OtherKey="customerId")]

  public EntitySet Orders {

    get { return this._Orders; }

    set { this._Orders.Assign(value); }

  }

}

Полученный код примечателен тем, что класс Customer является partial-классом, а это значит, что мы можем легко расширить его, и все прочие классы, для поддержки наших интерфейсов. Создадим частичные классы для реализации интерфейсов на базе LINQ для SQL так, как показано в листинге 3.2.

Листинг 3.2. Частичные классы с реализацией интерфейсов

public partial class Customer : ICustomer {

  public Guid CustomerId {

    get { return customerId; }

    set { customerId = value; }

  }

  public string Name {

    get { return name; }

    set { name = value; }

  }

  public string Phone {

    get { return phone; }

    set { phone = value; }

  }

  public string Address {

    get { return address; }

    set { address = value; }

  }

}

public partial class Order : IOrder {

  public Guid OrderId {

    get { return orderId; }

    set { orderld = value; }

  }

  public Guid Customerld {

    get { return customerId; }

    set { customerId = value; }

  }

  public Guid ProductId {

    get { return productId; }

    set { productId = value; }

  }

  public int Count {

    get { return count; }

    set { count = value; }

  }

  public DateTime OrderDateTime {

    get { return orderDateTime; }

    set { orderDateTime = value; }

  }

}

public partial class Product : IProduct {

  public Guid ProductId {

    get { return productId; }

    set { productId = value; }

  }

  public string Name {

    get { return name; }

    set { name = value; }

  }

  public bool IsAvailable {

    get { return isAvailable; }

    set { isAvailable = value; }

  }

  public decimal Cost {

    get { return cost; }

    set { cost = value; }

  }

}

На этом этапе существует еще одна полезная возможность, которую предлагает инъекция дополнительного кода: вы можете назначать имена для свойств интерфейса, не привязываясь к именам, которые определены в базе данных. Скажем, для поля cost таблицы Products мы могли бы задать другое название, например, ProductCost.


    Ваша оценка произведения:

Популярные книги за неделю