Как использовать простой инжектор, репозиторий и контекст — сначала код

Я пытаюсь использовать Simple Injector, чтобы создать свой репозиторий и использовать его на уровне бизнес-логики (также я хочу использовать метод PerWebRequest).

На уровне DAL у меня есть:

public interface IRepository<T> where T : class
{
    void Add(T entity);
    void Delete(T entity);
    void Delete(int id);
    void Update(T entity);
    T GetById(int Id);
    IQueryable<T> All();
    IEnumerable<T> Find(Func<T, bool> predicate);
}

и :

public class EFRepository<T> : IRepository<T>, IDisposable where T : class
{
    #region Members
    protected DbContext Context { get; set; }
    protected DbSet<T> DbSet { get; set; }
    #endregion

    #region Constructors

    public EFRepository(DbContext dbContext)
    {
        if (dbContext == null)
            throw new ArgumentNullException("dbContext");
        Context = dbContext;
        DbSet = Context.Set<T>();
    }

и мой контекст:

public class PASContext : DbContext, IDbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<User> Users { get; set; }

    public PASContext()
        : base("PostAndSell")
    { }
}

Как видите, EFRepository имеет только один конструктор, который принимает один аргумент, потому что я хочу использовать Simple Injector для создания экземпляра контекста и передачи его в репозиторий во время его создания.

В BLL у меня есть класс ProductBLL, и я хочу получить все продукты этого класса (с некоторым методом GetAll) из базы данных и передать их, скажем, HomeController.

Мне действительно нужно, чтобы кто-то рассказал мне об этом.

Я начал с установки нужных пакетов из nuger (Simple Injector и Simple Injector ASP.NET Integration)

также в моем файле global.asax.cs в функции Application_Start() я добавил:

var container = new SimpleInjector.Container();

container.RegisterPerWebRequest<IRepository<Product>, EFRepository<Product>>();

но где мне создать экземпляр Context? и как я могу получить к нему доступ на бизнес-уровне?


person jony89    schedule 15.12.2013    source источник


Ответы (1)


Поскольку у вас, вероятно, будет много реализаций IReposotory<T> (для продукта, клиента, сотрудника и т. д.), лучше сделать одну открытую общую регистрацию для IRepository<T> следующим образом:

container.Register(typeof(IRepository<>), typeof(EFRepository<>), Lifestyle.Scoped);

Где образ жизни с охватом определяется как:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

Эта регистрация гарантирует, что Simple Injector будет возвращать EFRepository<Product> каждый раз, когда запрашивается IRepository<Product>, EFRepository<Customer> для IRepository<Customer> и так далее, и так далее.

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

container.Register<DbContext, PASContext>(Lifestyle.Scoped);

В BLL у меня есть класс ProductBLL, и я хочу получить все продукты из базы данных и передать их, скажем, HomeController.

В этом сценарии этот ProductBLL кажется мне бесполезной абстракцией. Если все, что он делает, — это передача данных, вы можете легко позволить вашему HomeController напрямую зависеть от IRepository<Product>.

person Steven    schedule 15.12.2013
comment
Спасибо, но если у меня есть класс с логикой в ​​BLL, как я могу использовать репозиторий? моя концепция заключается в том, что BLL общается с DAL через репозитории, а MVC общается с BLL через такие классы, как productBLL . Кроме того, если я хочу получить доступ к этому репозиторию в HomeController, как я могу это сделать? и когда EF создаст базу данных? - person jony89; 15.12.2013
comment
Наличие класса BLL полезно только тогда, когда у вас действительно есть какая-то логика. Но если у вас есть логика, вам, конечно, нужно будет внедрить этот ProductBLL в ваш контроллер вместо продукта (или, если добавленное поведение касается исключительно сквозных задач, таких как ведение журнала, безопасность, проверка и т. д., вы можете добавить это с помощью декоратор на IRepository вместо этого). Если вы хотите получить доступ к репозиторию в контроллере, вы просто вводите IRepository‹T› в контроллер; в этом нет ничего необычного. Это просто работает. - person Steven; 15.12.2013
comment
как вы можете видеть, я довольно новичок в этом. как я могу просто внедрить IRepository‹Product› в контроллер? какой код связан со словом inject? как я могу получить доступ к Repostiroy в productBLL и ввести его в контроллер. Пожалуйста, покажите мне какой-нибудь код, связанный с этим. Кроме того, я до сих пор не вижу, где экземпляр PASContext передается конструктору EFRepository.. и когда будет создана база данных? так как это программа с кодом. - person jony89; 15.12.2013
comment
Если вы установили NuGet для быстрого запуска MVC, достаточно определить общедоступный конструктор на вашем контроллере, который принимает параметр типа IRepository‹Product›. Simple Injector сделает все остальное. - person Steven; 15.12.2013
comment
и если я хочу это в моем слое BLL? если вы можете, пожалуйста, ответьте на мои другие вопросы также в последнем комментарии. Спасибо. - person jony89; 15.12.2013
comment
При разрешении типа Simple Injector внедряет зависимости в конструктор этого типа. Если ваш HomeController зависит от BBLProducts, и вы разрешаете HomeController, Simple Injector создаст для вас BBLProducts. Если BBLProducts зависит от IRepository‹Product›, Simple Injector внедрит для вас EFRepository‹Product› в этот BBLProducts. Simple Injector создаст для вас полный граф связанных объектов. Вам нужно только разрешить корневой объект, и в случае MVC этот корневой объект (контроллер) разрешается за вас. - person Steven; 16.12.2013
comment
Как это сделать без использования PerWebRequest? Я использую OWIN, который не поддерживает HttpContext.Current, но я хотел бы использовать один и тот же контекст инфраструктуры сущностей для всех репозиториев. - person Shawn Mclean; 31.01.2014
comment
@ShawnMclean: у меня нет опыта работы с OWIN, но я думаю, что это заслуживает отдельной ветки на Simple Injector. дискуссионный форум. Какая модель программирования лежит в основе OWIN? Некоторым интересным вкладом в это обсуждение является модель программирования, лежащая в основе OWIN. Является ли он асинхронным, как веб-API? - person Steven; 01.02.2014
comment
@ShawnMclean: взгляните на эту тему. - person Steven; 01.02.2014
comment
Спасибо, @Steven, это я разместил вопрос, кстати. - person Shawn Mclean; 02.02.2014
comment
@ShawnMclean О, ха-ха .. Я просто не обратил внимания :-) - person Steven; 02.02.2014
comment
@Steven: Спасибо за общую регистрацию. Точно так же мое приложение имеет два сценария многоуровневого хранения: (1) простые контроллеры CRUD используют IEntityRepository<T>, и (2) бизнес-транзакции выполняются SomeService, который ожидает FooContext напрямую. Службы и контекст не имеют интерфейсов. SimpleInjector выдает ошибки времени выполнения, касающиеся короткозамкнутой зависимости и неоднозначного образа жизни, говоря, что FooContext является временным, а DbContext веб-запросом. Почему переходный? Достаточно отличается для нового вопроса? - person one.beat.consumer; 10.01.2017
comment
@one.beat.consumer, который абсолютно заслуживает нового вопроса. Будьте максимально конкретны в своем вопросе: покажите свой код, свои регистрации, детали сообщения об исключении и убедитесь, что вы прочитали документацию, на которую указывает сообщение об ошибке, прежде чем публиковать свой вопрос. - person Steven; 10.01.2017
comment
@Стивен: Спасибо. Вы можете найти его здесь - stackoverflow.com/q/41599706/146610 - person one.beat.consumer; 11.01.2017