Альтернативный поиск сервисов в ASP.NET MVC
Прочитав сообщение в блоге Марка Симанна вместе с ответом, который ссылается на него, я понял недостатки использования шаблона локатора службы по сравнению с внедрением зависимости через конструктор класса. Я также прочитал это внедрение зависимостей с помощью Ninject, MVC 3 и использование шаблона локатора служб, в котором также обсуждается эта проблема.
Тем не менее, мой вопрос касается этого конкретного случая:
public class MyController
{
public void GetData()
{
using (var repository = new Repository())
{
// Use the repository which disposes of an Entity Framework
// data context at the end of its life.
}
}
// Lots of other methods.
}
Здесь у меня есть контроллер, который содержит метод, который вызывает хранилище, которое автоматически создает внутренний контекст данных Entity Framework. Этот единственный контекст данных используется, потому что контекст вызывается каждым методом в хранилище, поэтому имеет смысл использовать один и тот же контекст на протяжении всего времени существования объекта хранилища.
Теперь, когда класс контроллера большой, существует большая вероятность, что данный репозиторий не будет использоваться. Поскольку я предполагаю (возможно, неправильно), что создание экземпляра DC является дорогостоящей операцией, я бы предпочел не делать этого. Использование шаблона локатора службы позволяет мне отложить создание экземпляра до тех пор, пока контекст фактически не понадобится, но, учитывая действительные аргументы против него в приведенных выше ссылках, я бы предпочел избежать этого.
Так что я хотел бы знать, есть ли более эффективный способ использования внедрения зависимостей в вышеупомянутом случае, который бы помешал мне без необходимости создавать экземпляр моего хранилища и нижележащий контекст данных.
3 ответа
Я думаю, что ответ зависит от того, как ваш репозиторий управляет соединениями. Если при создании он открывает соединение с базой данных, то, я думаю, проблема в вашем репозитории, а не в Dependency Injection. Ваш репозиторий должен открывать соединение только тогда, когда сделан запрос, и закрывать его, как только получен ответ. Следуя этой схеме, внедрение зависимостей все еще имеет смысл.
Исходя из вашего обновления, вам все-таки лучше использовать DI, потому что EF не открывает соединение с базой данных при построении, только когда сделан запрос. Ваш контекст данных настолько мал, что стоит небольшого количества накладных расходов, необходимых для создания контекста для каждого запроса.
Еще один комментарий: вам также следует подумать о том, чтобы вставить свой контекст данных в свои репозитории и позволить контейнеру DI контролировать время существования контекста. Это позволяет использовать один и тот же контекст в одном или нескольких хранилищах во время одного запроса. Вот довольно хороший ресурс, объясняющий, как реализовать шаблоны Repository и Unit of Work с помощью Entity Framework в ASP.NET MVC.
Поскольку класс контроллера велик, существует большая вероятность, что соединение не будет использоваться ни в одной конкретной конструкции, поэтому нет смысла создавать экземпляр репозитория и открывать соединение, используя стандартный DI на основе конструктора.
Внедрить Lazy
, Func
или вместо фабрики:
public class MyController
{
// Use constructor injection to populate this.
private Func<MyRepository> _repository;
public void GetData()
{
using (var repository = _repository())
{
// ...
}
}
}
Таким образом, вы можете избежать создания реальных экземпляров, пока они вам не понадобятся.
Ответ @sellmeadog тоже хорош.
Вы спрашиваете, стоит ли вводить соединение с базой данных в конструктор репозитория? Вы можете попробовать использовать шаблон проектирования Abstract Factory, внедряющий фабрику соединений с базой данных вместо фактического соединения с базой данных.
public class MyController
{
public void GetData()
{
using (var repository = new Repository(IDatabaseConnectionFactory dbConnFac))
{
// Use the repository which disposes of a database connection
// at the end of its life.
}
}
// Lots of other methods.
}
Таким образом, вы получаете преимущества внедрения зависимостей, в то же время позволяя репозиторию управлять жизненным циклом своих соединений с базой данных.