Как внедрить Entity Framework DbContext в ConfigurationBasedRepository of SharpRepository
Я действительно хотел бы использовать SharpRepository вместе с Ninject, но я не понимаю, как настроить Ninject для совместного использования Entity Framework DbContext между репозиториями.
Я использую Entity Framework версии 5 и Ninject версии 3.
В настоящее время я использую Ef5Repository
в своем исходном коде, но я хочу заменить его на ConfigurationBasedRepository
. Но я не могу понять, как передать (или ввести) EF DbContext
в репозитории.
Пример (текущее состояние):
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
using SharpRepository.Ef5Repository;
using System.Data.Entity;
// TODO Tightly coupled to Ef5Repository.
public class ProductRepository : Ef5Repository<Product>, IProductRepository
{
// TODO The DbContext has to be injected manually.
public ProductRepository(DbContext context) : base(context)
{
}
// [...]
}
Цель:
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
// [...]
}
Я уже прочитал два сообщения в блоге SharpRepository: Начало работы и SharpRepository: Конфигурация, но оба они мне не помогают, поскольку:
- Используемый DIC - это StructureMap, а не Ninject.
- Примеры исходного кода являются неполными (например, использование не объявленных переменных).
Итак, мой вопрос: может ли кто-нибудь предоставить мне пример практического примера исходного кода для достижения цели, описанной выше (общий экземпляр Entity Framework DbContext
между всеми репозиториями, расширяющими ConfigurationBasedRepository
)?
Ответы
Ответ 1
Сначала вам нужно установить пакет SharpRepository.Ioc.Ninject NuGet. Существуют методы расширения здесь для подключения Ninject для обработки загрузки общего репозитория и установки зависимого преобразователя, который использует SharpRepository.
Где бы вы ни настраивали свои правила привязки Ninject (все вызовы kernel.Bind < > ), вам нужно будет добавить:
kernel.BindSharpRepository();
Далее, в вашем коде Global.asax или App_Start или в логике Bootstrapper (где бы вы ни называли код запуска приложения) вам нужно добавить следующее:
// kernel is the specific kernel that you are setting up all the binding for
RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));
Это позволит SharpRepository использовать это ядро Ninject при получении нового DbContext.
Последнее, что нужно сделать, это установить правила привязки для самого DbContext. Если вы находитесь в веб-приложении, вам, скорее всего, понадобится объем DbContext для каждого запроса. Я лично не использую Ninject, но я нашел эту ссылку для использования InRequestScope. Я считаю, что ваш код будет выглядеть примерно так:
kernel.Bind<DbContext>().To<MyCustomEfContext>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["MyCustomEfContext"].ConnectionString);
Большинство людей не будут нуждаться в этой следующей части, но если у вас есть пользовательская логика в вашем CustomEfContext (у меня есть переопределение для входа в вызовы SaveChanges()), тогда вам нужно будет определить свой собственный тип контекста в конфигурационный файл:
<repositories>
<repository name="ef5Repository" connectionString="CustomEfContext" cachingStrategy="standardCachingStrategy" dbContextType="My.Data.CustomEfContext, My.Data" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" />
</repositories>
Где dbContextType определяет тип настраиваемого DbContext, который вы используете, используя полный тип синтаксиса пространства имен. Если вы это сделаете, вам нужно установить Ninject в Bind в пользовательский контекст, изменив значение .Bind <DbContext> () на .Bind <CustomEfContext> (). Но, как я уже сказал, вы можете напрямую использовать DbContext без проблем.
Ответ 2
Прежде всего, решение, предоставленное в ответе Джеффом Т, работает!
Я завершу шаги, которые я предпринял, чтобы сделать Ninject работать в проекте ASP.NET MVC 4 + EF 5. Важно отметить, что шаблон конкретного репозитория реализован с помощью SharpRepository в следующем примере.
Необходимое программное обеспечение
- Установите Ninject и "Ninject.MVC3" (который также устанавливает "Ninject.Web.Common" ) через NuGet.
- Установите SharpRepository, "SharpRepository для EF5" и "SharpRepository с Ninject IOC" через NuGet.
Определить слой репозитория
-
Создайте DbContext производный класс, например. Domain.EfContext
. Это
"Рекомендуемый способ работы с контекстом".
-
Определите интерфейс для конкретного репозитория, например:
// TODO By extending IRepository, the interface implements default Create-Read-Update-Delete (CRUD) logic.
// We can use "traits" to make the repository more "specific", e.g. via extending "ICanInsert".
// https://github.com/SharpRepository/SharpRepository/blob/master/SharpRepository.Samples/HowToUseTraits.cs
public interface IProjectRepository : IRepository<Project>
{
// TODO Add domain specific logic here.
}
-
Определите класс, который реализует конкретный репозиторий и наследует от SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>
, например:
public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
// TODO Implement domain specific logic here.
}
Определить потребительский уровень
-
Создайте контроллер, например. Controllers.ProductController
.
public class ProductController : Controller
{
private IProductRepository Repository { get; private set; }
// TODO Will be used by the DiC.
public ProductController(IProductRepository repository)
{
this.Repository = repository;
}
}
Настроить инъекцию зависимостей (DI) через контейнер инжекции зависимостей (DiC) Ninject
Файл App_Start/NinjectWebCommon.cs
автоматически создается Ninject.Web.Common, и мы можем загружать наши модули и регистрировать наши службы в методе RegisterServices(IKernel kernel) : void
класса NinjectWebCommon
.
Вот полный исходный код этого метода для примера:
private static void RegisterServices(IKernel kernel)
{
kernel.BindSharpRepository();
RepositoryDependencyResolver.SetDependencyResolver(
new NinjectDependencyResolver(kernel)
);
string connectionString = ConfigurationManager.ConnectionStrings["EfContext"].ConnectionString;
kernel.Bind<DbContext>()
.To<EfContext>()
.InRequestScope()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<IProductRepository>().To<ProductRepository>();
}
Определите следующий раздел sharpRepository
в Web.config
:
<sharpRepository>
<repositories default="ef5Repository">
<repository name="ef5Repository"
connectionString="EfContext"
cachingStrategy="standardCachingStrategy"
dbContextType="Domain.EfContext, Domain"
factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository"
/>
</repositories>
</sharpRepository>
Кроме того, раздел connectionStrings
, чтобы сделать пример завершенным (я использую SQL Server LocalDB).
<connectionStrings>
<add name="EfContext" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=Domain;Integrated Security=True" />
</connectionStrings>
Я надеюсь, что этот вывод поможет другим людям получить ASP.NET MVC 4 вместе с Entity Framework 5 и SharpRepository и работать!
Пожалуйста, оставьте мне ответ, если я сделаю один или несколько ненужных шагов или вы увидите возможности для улучшения архитектуры, описанной в примере.
Btw, я имел, чтобы добавить атрибут dbContextType
в раздел repository
, чтобы он работал (в отличие от ответа Jeff T).
Забастовкa >
EDIT (2013-08-28): Удалены ненужные шаги (не требуются с последней версией SharpRepository).