Является ли репозиторий Singleton или Static, или нет? - PullRequest
14 голосов
/ 18 сентября 2011

У меня есть веб-сайт ASP.NET, который использует дизайн, управляемый доменом, и использует репозиторий для своих операций с базой данных.
Я хочу знать, в чем плюсы и минусы одноэлементного репозитория и статического репозитория, а также простого класса репозитория, который будет новымпри каждом доступе?
еще больше, если кто-нибудь сможет сравнить и подсказать мне, какой из них я буду признателен.

Ответы [ 4 ]

15 голосов
/ 19 сентября 2011

Static и singleton не являются хорошим решением для шаблона репозитория.Что если ваше приложение будет использовать 2 или более репозитория в будущем?

IMO лучшее решение - использовать контейнер внедрения зависимостей и внедрить интерфейс IRepository в те классы, которые в этом нуждаются.

Я предлагаю вам прочитать хорошую книгу о доменно-ориентированном проектировании и хорошую книгу о внедрении зависимостей (например, Внедрение зависимостей в .NET ).


С помощью синглетонов и статических классов ваше приложение не будет масштабируемым

У вас есть два одноэлементных репозитория:

class Repository<TEntity> {

  static Repository<TEntity> Instance { get { ... /*using sql server*/ } }
}

class Repository2<TEntity> {

  static Repository2<TEntity> Instance { get { ... /*using WCF or XML or any else */ } }
}

Службы, использующие их, должны иметь статическую ссылку на один из них или оба:

class OrderService {

    public void Save(Order order) { Repository<Order>.Instance.Insert(order); }
}

Как сохранить заказ с помощью Repository2, если на репозиторий статическая ссылка ?

Лучшим решением является использование DI:

interface IRepository<TEntity> { ... }

class SqlRepository<TEntity> : IRepository<TEntity> { ....}

class OrderService {
    private readonly IRepository<TEntity> _repo;

    public OrderService(IRepository<TEntity> repo) { _repo = repo; }

    public void Save(Order order) { repo.Insert(order); }
}
6 голосов
/ 19 сентября 2011

Не используйте статические или одноэлементные репозитории из-за:

  • Это влияет на тестабельность, вы не можете издеваться над ним при юнит-тестировании.

  • Это влияет на расширяемость, вы не можете сделать более одной конкретной реализации и не можете заменить поведение без повторной компиляции.

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

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

Итог: НЕ используйте статические или одноэлементные репозитории

, вместо этого создайте интерфейсы репозитория в своем проекте модели домена, внедрите эти интерфейсы в конкретный проект доступа к данным и используйте инфраструктуру внедрения зависимостей.

4 голосов
/ 20 сентября 2011

Два SOLID причины отсутствия одноэлементного хранилища:

  • Потребители хранилища будут связаны с реализацией хранилища. Это негативно скажется на расширяемости и тестабилии. Это нарушение DIP . Зависит от абстракций, а не от конкрементов.

  • Реализация репозитория должна будет нарушать SRP , поскольку она, скорее всего, в конечном итоге приведет к управлению сеансом ORM, подключением к базе данных и, возможно, транзакциями. Это также должно было бы обеспечить гарантии безопасности потока, потому что он потенциально может быть использован из нескольких потоков. Вместо этого соединение с базой данных (сеанс ORM) следует внедрить в реализацию репозитория, чтобы потребляющий код мог организовать несколько вызовов репозитория в транзакцию.

Возможное решение обеих проблем: Инъектор конструктора .

3 голосов
/ 27 марта 2012

Я лично с уважением не согласен с предыдущими ответами.

Я разработал несколько веб-сайтов (один с 7 миллионами просмотров страниц в месяц), и у меня никогда не было ни одной проблемы с моими статическими репозиториями.

МойРеализация статического репозитория довольно проста и содержит только объекты поставщиков в качестве свойств.Один репозиторий может содержать столько поставщиков, сколько вам нужно.

Затем поставщики отвечают за управление подключением к базе данных и транзакциями.Используя TransactionScope, потребитель может управлять транзакциями или передавать их поставщикам.

Все поставщики разрабатываются с использованием шаблона singleton.

Таким образом, я могу получить свои объекты, просто вызвав это:

var myObj = MyRepository.MyProvider.GetMyObject(id);

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

Я не вижу, где находится мой репозиторий /Поставщики, потребители связаны с моим хранилищем.Фактически, реализации моих провайдеров полностью абстрагированы от них.Конечно, все провайдеры, возвращаемые моим репозиторием, являются интерфейсами, и я мог легко изменить их реализацию в любое время и вставить свою новую dll на веб-сервер.Если я хочу создать совершенно нового провайдера с тем же интерфейсом, мне нужно только изменить его в ОДНОМ месте: в моем репозитории.

Таким образом, нет необходимости добавлять внедрение зависимостей или создавать свой собственный ControllerFactory (для MVC-проектов).

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

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

...