如何将实体框架DbContext注入SharpRepository的ConfigurationBasedReposito

本文关键字:注入 SharpRepository ConfigurationBasedReposito DbContext 框架 实体 | 更新日期: 2023-09-27 18:10:36

我真的很想将SharpRepository与Ninject一起使用,但我不知道如何配置Ninject以在存储库之间共享实体框架DbContext。

我使用的是EntityFramework版本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:Getting Started和SharpRepository:Configuration这两篇博客文章,但它们都对我没有帮助,因为:

  1. 使用的DIC是StructureMap,而不是Ninject
  2. 源代码示例不完整(例如使用未声明的变量(

因此,我的问题是:有人能为我提供一些源代码示例,说明如何实现上述目标(在所有扩展ConfigurationBasedRepository的存储库之间共享一个实体框架DbContext实例(吗?

如何将实体框架DbContext注入SharpRepository的ConfigurationBasedReposito

首先,您需要安装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在获取新的DbContext时使用此Ninject内核。

最后要做的是为DbContext本身设置绑定规则。如果你在一个web应用程序中,你很可能希望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>((到。绑定<自定义上下文>((。但就像我通常说的那样,你可以直接使用DbContext而没有问题。

首先,Jeff T在答案中提供的解决方案有效!

我将总结我为使Ninject在ASP.NET MVC 4+EF 5项目中工作所采取的步骤。值得一提的是,特定存储库模式是通过以下示例中的SharpRepository实现的。


所需软件

  1. 通过NuGet安装Ninject和"Ninject.MVC3"(也安装"Ninject.Web.Common"(
  2. 通过NuGet安装SharpRepository、"SharpRepositoryforEF5"answers"SharpReservewithNinjectIOC">

定义存储库

  1. 创建一个DbContext派生类,例如Domain.EfContext。这是

    "使用上下文的推荐方法"。

    • 将所有必需的DbSet<T>声明为公共属性,例如public DbSet<Product> Products { get; set; }
    • 在类Domain.EfContext:中声明以下两个构造函数

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

  2. 特定存储库定义接口,例如:

    // 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.
    }
    
  3. 定义一个实现特定存储库并从SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>继承的类,例如:

    public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
    {
        // TODO Implement domain specific logic here.
    }
    

定义消费者

  1. 创建一个控制器,例如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;
        }
    }
    

通过依赖注入容器(DiC(Ninject设置依赖注入(DI(

文件App_Start/NinjectWebCommon.cs由Ninject.Web.Common自动创建,我们可以在类NinjectWebCommon的方法RegisterServices(IKernel kernel) : void中加载模块并注册服务。以下是该方法的完整源代码示例:

    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>();
    }

Web.config:中定义以下sharpRepository部分

    <sharpRepository>
        <repositories default="ef5Repository">
            <repository name="ef5Repository"
                connectionString="EfContext"
                cachingStrategy="standardCachingStrategy"
                dbContextType="Domain.EfContext, Domain"
                factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository"
            />
        </repositories>
    </sharpRepository>

此外,connectionStrings部分使示例更加完整(我使用的是SQLServerLocalDB(。

    <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结合起来并运行起来!

如果我采取了一个或多个不必要的步骤,或者您看到了改进示例中描述的架构的可能性,请给我一个答复。

顺便说一句,我不得不dbContextType属性添加到repository部分以使其工作(与Jeff T的回答相反(。


编辑(2013-08-28(:删除了不必要的步骤(最新版本的SharpRepository不需要(。