Подтвердить что ты не робот

Как внедрить 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)?

4b9b3361

Ответ 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. Это

    "Рекомендуемый способ работы с контекстом".

    • Объявить все обязательные DbSet<T> как общедоступные свойства, например. public DbSet<Product> Products { get; set; }
    • Объявить следующие два конструктора в классе Domain.EfContext:

      public EfContext() : base() {}
      public EfContext(string connectionName) : base(connectionName) {}
      

      удаp >

  • Определите интерфейс для конкретного репозитория, например:

    // 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).