Паттерн «Репозиторий» в качестве модели в ASP.NET MVC

Как известно, в MVC модель содержит в себе бизнес-логику приложения и, при необходимости, обеспечивает доступ к данным хранящимся в БД. При этом если учитывать, что подавляющее большинство веб приложений ASP.NET MVC строятся на основе различных СУБД, взаимодействие модели с БД становится насущной потребностью.

Ранее уже рассматривалась архитектура паттерна «Репозиторий», его реализация на C#, а также те преимущества, которые он предоставляет.

Вероятно, с первого взгляда смысл его использования покажется не совсем понятным. Ведь есть LINQ to SQL, Entity Framework и прочие ORM библиотеки, которые по сути уже реализуют весь необходимый функционал. Почему не работать в контроллерах напрямую с ними? Зачем лишние усложнения?

На самом же деле применение данного паттерна является вовсе не лишним и имеет объективные причины.

  • Технология ORM не подразумевает реализацию бизнес-логики. Она всего лишь позволяет более качественно организовать взаимодействие с БД путём отображения её структуры на классы и объекты языка программирования.
    В тоже время класс реализующий паттерн «Репозиторий» можно легко расширить, добавив в него необходимые функции;
  • Объектная модель, созданная с помощью ORM жёстко «привязана» к конкретной БД и её структуре. Паттерн «Репозиторий» позволяет изолировать работу непосредственно с БД от остальной части приложения. Это позволяет реализовать поддержку нескольких БД и даже СУБД, практически не изменяя логику работы клиентской части.

Реализация паттерна «Репозиторий» применительно к моделям в ASP.NET MVC в принципе особой сложности не представляет, хотя в ней и присутствуют некоторые особенности.

Реализация непосредственно паттерна «Репозиторий»

Так как все классы «репозитории» будут связаны с одной и той же БД, целесообразно выделить общий для всех них функционал в абстрактный базовый класс.

public abstract class Repository
{
    protected DataContext _dc;
    public Repository(DataContext dc)
    {
        _dc = dc;
    }
}

Все остальные классы будут добавлять только логику специфическую для каждого конкретного случая. Все свои основные возможности они будут получать от базового класса путём наследования (паттерн «Супертип слоя«).

public class DaysRepository : Repository
{
    public DaysRepository(DataContext dc) : base(dc)
    {
    }
    public IEnumerable<vDays> GetDays()
    {
        return _dc.vDays.OrderByDescending(t => t.DayDate);
    }
    public vDays GetDay(Guid id)
    {
        return _dc.vDays.SingleOrDefault(t => t.id == id);
    }
    public void CreateDay(DateTime d)
    {
        _dc.AddNewDay(d);
    }
    public void UpdateDay (vDays v)
    {
        vDays vd = GetDay(v.id);
       _dc.UpdateDay(vd.id, vd.DayDate);
    }
    public void DeleteDay(Guid id)
    {
       _dc.DeleteDay(id);
    }
}

Интеграция паттерна «Репозиторий» в проект ASP.NET MVC

Как показано выше, реализация паттерна «Репозиторий» в ASP.NET MVC действительно не представляет особого труда. В тоже время для работоспособности приложения этого недостаточно.

Необходимы инициализация подключения к БД и создание экземпляров классов «репозиториев».

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

public class DataManager
{
   private DataContext _dc;
   public DataManager(string connectionString)
   {
       _dc = new DataContext(connectionString);
   }
   private DaysRepository _daysRepository;
   public DaysRepository Days
   {
       get
       {
           if (_daysRepository== null)
           {
               _daysRepository = new DaysRepository(_dc);
           }
           return _daysRepository;
       }
   }
}

С помощью экземпляра этого класса и будет осуществляться доступ к модели в контроллере.

public class DaysController : Controller
{
    private DataManager _dm;
    public DaysController(DataManager dm)
    {
        _dm = dm;
    }
. . .
}

 Однако этот экземпляр также требуется создать. Для этого служит специальная фабрика.
public class SCO_ControllerFactory: DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return (IController)Activator.CreateInstance(controllerType, new DataManager(WebConfigurationManager.ConnectionStrings["TestDBConnectionString"].ConnectionString;));
    }
}

В свою очередь, данная фабрика должна быть зарегистрирована в Global.asax.

protected void Application_Start()
{
. . .
    ControllerBuilder.Current.SetControllerFactory(new SCO_ControllerFactory());
. . .
}

Только после правильного выполнения всех вышеописанных операций паттерн «Репозиторий» будет интегрирован в проект и приложение сможет выполнять свои функции.

Можно справедливо отметить, что процесс интеграции гораздо сложнее, чем сама его реализация. Но, к сожалению, эти издержки обусловлены самой архитектурой ASP.NET MVC.

Однако в любом случае положительный эффект, получаемый в результате, вполне оправдан и, если выполнить все вышеописанные операции внимательно, паттерн «Репозиторий» будет интегрирован в проект без каких-либо проблем и особых временных затрат.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *