У меня есть веб-сайт ASP.NET, который использует проект, управляемый доменами, и использует репозиторий для своих операций с базой данных.
Я хочу знать, что такое плюсы и минусы репозитория singleton и статического репозитория и простого класса репозитория, который будет новым при каждом доступе?
еще больше, если кто-нибудь может сравнить и направить меня к использованию, какой из них я буду признателен.
Является ли репозиторий синглтон или статический или ни один из них?
Ответ 1
Статический и singleton не являются хорошим решением для шаблона репозитория. Что делать, если ваше приложение будет использовать 2 или более хранилища в будущем?
IMO лучшим решением является использование контейнера для инъекций зависимостей и встраивание интерфейса IRepository в классы, которые в нем нуждаются.
Я предлагаю вам прочитать хорошую книгу о дизайне, ориентированном на домен, и хорошую книгу об инъекции зависимостей (например, Mark Seeman Dependency Injection in.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); }
}
Ответ 2
Не используйте статические или одноэлементные репозитории из-за:
-
Это влияет на testablility, вы не можете издеваться над ним при модульном тестировании.
-
Это влияет на расширяемость, вы не можете сделать более одной конкретной реализации, и вы не можете заменить поведение без повторной компиляции.
-
Это влияет на масштабируемость с точки зрения управления жизненным циклом, insetead зависит от структуры инъекции зависимостей, чтобы вносить зависимость и управлять жизненным циклом.
-
Он влияет на ремонтопригодность, он заставляет зависимость от конкретной реализации вместо абстракции.
Нижняя строка: DONT использует статические или одноэлементные репозитории
вместо этого создайте интерфейсы репозитория в вашем проекте модели домена и реализуйте эти интерфейсы в конкретном проекте доступа к данным и используйте инфраструктуру впрыска зависимостей.
Ответ 3
Два SOLID причины не иметь одноэлементного репозитория:
-
Потребители репозитория будут связаны с реализацией репозитория. Это негативно скажется на расширяемости и тестируемости. Это нарушение DIP. Зависит от абстракций, а не от конкреций.
-
Репозиторий будет вынужден нарушать SRP, поскольку, скорее всего, это приведет к управлению сеансом ORM, подключению к базе данных и потенциальным транзакциям, Он также должен был бы обеспечить надежные гарантии потока, поскольку он потенциально может использоваться из нескольких потоков. Вместо этого соединение с базой данных (сеанс ORM) должно быть внедрено в реализацию репозитория, так что код потребления может организовать несколько вызовов репозитория в транзакцию.
Возможное решение обеих проблем: Инъекция конструктора.
Ответ 4
Я лично с уважением не согласен с предыдущими ответами.
Я разработал несколько веб-сайтов (один с 7 миллионами просмотров страниц в месяц) и никогда не имел ни одной проблемы с моими статическими репозиториями.
Моя статическая реализация репозитория довольно проста и содержит только объекты-поставщики в качестве свойств. Один репозиторий может содержать столько поставщиков, сколько вам нужно.
Затем поставщики отвечают за управление подключением к базе данных и транзакциями. Используя TransactionScope, потребитель мог управлять транзакциями или предоставлять их поставщикам.
Каждый поставщик разрабатывается с использованием шаблона singleton.
Таким образом, я могу получить свои объекты, просто называя это:
var myObj = MyRepository.MyProvider.GetMyObject(id);
В любой момент в каждом веб-пуле моего приложения есть только один репозиторий и один поставщик каждого типа. В зависимости от того, сколько пользователей вы одновременно используете на своем сайте, вы можете установить более одного веб-пула (но в большинстве случаев этого достаточно).
Я не вижу, где мои пользователи репозитория/провайдеров связаны с моим репозиторием. Фактически, реализации моих провайдеров полностью абстрагированы от них. Конечно, все провайдеры, возвращаемые моим репозиторием, являются интерфейсами, и я мог бы легко изменить их реализацию в любое время и направить мою новую dll на веб-сервер. Если я хочу создать совершенно новый провайдер с тем же интерфейсом, мне нужно изменить его только в одном месте: мой репозиторий.
Таким образом, не нужно добавлять инъекцию зависимостей или создавать собственный ControllerFactory (для MVC-программ).
И у вас все еще есть преимущество чистого кода в ваших контроллерах. Вы также сохраните большое количество создания и уничтожения репозитория каждый раз, когда запрашивается страница (которая обычно использует отражение в вашем ControllerFactory).
Если вы ищете масштабируемое решение (если вам это действительно нужно, в большинстве случаев это не проблема), мой способ разработки репозиториев никогда не должен быть проблемой по сравнению с инъекцией зависимостей.