问题 如何使用简单的注入器,存储库和上下文 - 首先编码


我正在尝试使用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实例?以及如何在业务层中访问它?


10535
2017-12-15 12:17


起源



答案:


既然你可能会有很多 IReposotory<T> 实现(对于产品,客户,员工等),最好进行单一的开放式通用注册 IRepository<T> 喜欢这个:

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

范围生活方式定义为:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

此注册确保Simple Injector将返回a EFRepository<Product>,每一次 IRepository<Product> 请求, EFRepository<Customer> 对于 IRepository<Customer>, 等等等等。

既然你想要一样 DbContext 要在同一请求中的所有存储库上使用的实例,您还应该注册 DbContext 与生活方式的生活方式:

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

在BLL我有一个ProductBLL类,我想得到所有产品   从数据库中传递给它,让我们说HomeController

在那种情况下,这个 ProductBLL 对我来说似乎是一种无用的抽象。如果它只是传递数据,你可以轻松地让你的 HomeController 取决于 IRepository<Product> 直。


16
2017-12-15 12:34



谢谢,但如果我在BLL中有一些逻辑类,我该如何使用存储库?我的概念是BLL通过存储库和MVC通过类似productBLL的类与BLL进行对话。此外,如果我想在HomeController中访问此存储库,我该怎么办?当EF将创建数据库? - jony89
拥有BLL类只有在您实际拥有任何逻辑时才有用。但是如果你有逻辑,你当然需要将ProductBLL注入你的控制器而不是产品(或者如果添加的行为只是交叉问题,如日志记录,安全性,验证等,你可以使用而不是IRepository上的装饰器)。如果要访问控制器中的repo,只需将IRepository <T>注入控制器;这没什么好看的。这才有效。 - Steven
你可以看到我对这个很新手。我怎样才能简单地“注入”IRepository <Product>到控制器中?什么代码与“注入”一词有关?我怎样才能访问Repostiroy productBLL并将其注入控制器 - 请向我展示一些与此相关的代码。另外我还是看不到一个实例 PASContext 传递给了 EFRepository 构造函数..什么时候创建数据库?因为这是代码优先的程序。 - jony89
如果你已经安装了MVC Quick Start NuGet,那么只需在控制器上定义一个带有IRepository <Product>类型参数的公共构造函数。简单的注射器将完成剩下的工作。 - Steven
解析类型时,Simple Injector会将依赖项注入到该类型的构造函数中。如果您的HomeController依赖于BBLProducts,并且您解析了HomeController,Simple Injector将为您创建BBLProducts。如果BBLProducts依赖于IRepository <Product>,Simple Injector将为您注入一个EFRepository <Product>到该BBLProducts中。 Simple Injector将为您构建相关对象的完整图表。您只需解析根对象,在MVC的情况下,将为您解析此根对象(控制器)。 - Steven


答案:


既然你可能会有很多 IReposotory<T> 实现(对于产品,客户,员工等),最好进行单一的开放式通用注册 IRepository<T> 喜欢这个:

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

范围生活方式定义为:

container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

此注册确保Simple Injector将返回a EFRepository<Product>,每一次 IRepository<Product> 请求, EFRepository<Customer> 对于 IRepository<Customer>, 等等等等。

既然你想要一样 DbContext 要在同一请求中的所有存储库上使用的实例,您还应该注册 DbContext 与生活方式的生活方式:

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

在BLL我有一个ProductBLL类,我想得到所有产品   从数据库中传递给它,让我们说HomeController

在那种情况下,这个 ProductBLL 对我来说似乎是一种无用的抽象。如果它只是传递数据,你可以轻松地让你的 HomeController 取决于 IRepository<Product> 直。


16
2017-12-15 12:34



谢谢,但如果我在BLL中有一些逻辑类,我该如何使用存储库?我的概念是BLL通过存储库和MVC通过类似productBLL的类与BLL进行对话。此外,如果我想在HomeController中访问此存储库,我该怎么办?当EF将创建数据库? - jony89
拥有BLL类只有在您实际拥有任何逻辑时才有用。但是如果你有逻辑,你当然需要将ProductBLL注入你的控制器而不是产品(或者如果添加的行为只是交叉问题,如日志记录,安全性,验证等,你可以使用而不是IRepository上的装饰器)。如果要访问控制器中的repo,只需将IRepository <T>注入控制器;这没什么好看的。这才有效。 - Steven
你可以看到我对这个很新手。我怎样才能简单地“注入”IRepository <Product>到控制器中?什么代码与“注入”一词有关?我怎样才能访问Repostiroy productBLL并将其注入控制器 - 请向我展示一些与此相关的代码。另外我还是看不到一个实例 PASContext 传递给了 EFRepository 构造函数..什么时候创建数据库?因为这是代码优先的程序。 - jony89
如果你已经安装了MVC Quick Start NuGet,那么只需在控制器上定义一个带有IRepository <Product>类型参数的公共构造函数。简单的注射器将完成剩下的工作。 - Steven
解析类型时,Simple Injector会将依赖项注入到该类型的构造函数中。如果您的HomeController依赖于BBLProducts,并且您解析了HomeController,Simple Injector将为您创建BBLProducts。如果BBLProducts依赖于IRepository <Product>,Simple Injector将为您注入一个EFRepository <Product>到该BBLProducts中。 Simple Injector将为您构建相关对象的完整图表。您只需解析根对象,在MVC的情况下,将为您解析此根对象(控制器)。 - Steven