Плохо ли иметь репозиторий, который вручную открывает и закрывает соединение с БД? - PullRequest
0 голосов
/ 13 февраля 2012

Среда: ASP.NET MVC3 C #

Скажите, у меня есть хранилище (полупсевдо):

public interface IRepository
{
 create();read();update();delete();opendb();closedb();
}

public class CarRepository : IRepository
{
 private DbContext namedDbContext;

 public void opendb()
 {
  namedDbContext = new DbContext();
 }
 public void closedb()
 {
  namedDbContext.dispose();
 }
}

И затем в контроллер вводится хранилище, которое используется для ручного управления временем жизни БД:

public class SomeController : Controller
{
    private IRepository CarRepository;

    public void SomeController(IRepository _carRepository)
    {
        CarRepository = _carRepository;
    }

    public ActionResult SomeAction(int CarId)
    {
        CarRepository.opendb();
        var car = CarRepository.read(CarId);
        CarRepository.closedb();
    }
}

Считается ли это плохой практикой, поскольку он берет контроль над соединением из хранилища и помещает его в контроллер? Меня беспокоит утечка памяти при использовании внедрения зависимостей, и я хочу убедиться, что дублированные соединения не открыты, не работают и не используются долго.

Ответы [ 3 ]

2 голосов
/ 13 февраля 2012

Да.Конечно.Большинство драйверов ADO.NET используют пул соединений, поэтому сам процесс соединения не такой уж тяжелый.И у вас есть TransactionScope, который может позаботиться о транзакции по нескольким соединениям, но это будет не так быстро, как одна транзакция по одному соединению.

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

IoC гарантированно очистит соединение (в этом убедилась большая база пользователей).Нет никакой гарантии, что программист выполнит очистку во всех местах.

1 голос
/ 13 февраля 2012

Шаблон REpository обеспечивает абстракцию постоянного уровня. Он не должен раскрывать какие-либо детали персистентности, такие как соединение с БД. Что если хранилище представляет собой файл XML или облачное хранилище?

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

КАК для утечек памяти, сделайте IDIsposable репозитория (где вы закрываете все открытые соединения) и просто убедитесь, что контейнер DI управляет экземпляром репозитория для каждого запроса, он вызовет для него Dispose.

1 голос
/ 13 февраля 2012

Часть репозитория абстрагирует детали персистентности.

Я вижу две проблемы с вашим предложением:

  1. Вы пропускаете абстракцию больше, чем необходимо, называя эти методы«opendb» и «closedb» и
  2. Если вы идете по этому маршруту, вы должны вернуть IDisposable (объект соединения) из метода opendb() и заключить действие в блок using вубедитесь, что соединение закрыто.

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

Чтобы достичь этого, вы можете раскрыть понятие единицы работы из хранилища.Ваша единица работы будет реализовывать интерфейс для методов хранилища, поэтому вы не можете вызывать их вне единицы работы.Он также реализует IDisposable, поэтому всякий раз, когда вы заходите в свой репозиторий, вы будете использовать блок using.Внутри хранилище будет управлять соединением, но не будет раскрывать соединение и «говорить об этом».

Например:

public ActionResult SomeAction(int CarId)
{
     using (var repo = CarRepository.BeginUnitOfWork())
     {
        var car = repo.read(CarId);
        // do something meaningful with the car, do more with the repo, etc.
     }
}
...