如何将Entity Framework DbContext注入SharpRepository的ConfigurationBasedRepository

时间:2013-04-23 14:48:28

标签: c# entity-framework repository ninject sharp-repository

我真的想将SharpRepositoryNinject一起使用,但我不明白如何配置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: Getting StartedSharpRepository: Configuration,但他们都没有帮助我,因为:

  1. 使用的DIC是StructureMap,而不是Ninject。
  2. 源代码示例不完整(例如使用未声明的变量)。
  3. 所以我的问题:有人能为我提供一些源代码示例,以实现上述目标(在扩展DbContext的所有存储库之间共享一个实体框架ConfigurationBasedRepository实例)?

2 个答案:

答案 0 :(得分:16)

首先,您需要安装SharpRepository.Ioc.Ninject NuGet package。这里有一些扩展方法,用于连接Ninject以处理加载通用存储库和设置SharpRepository使用的依赖解析器。

无论您在哪里设置Ninject绑定规则(对kernel.Bind&lt;&gt;的所有调用),您都需要添加:

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的类型。如果你这样做,那么你需要通过将.Bind&lt; DbContext&gt;()更改为.Bind&lt; CustomEfContext&gt;()来将Ninject设置为自定义上下文。但就像我通常说的那样,你可以直接使用DbContext而不会出现问题。

答案 1 :(得分:6)

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

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


必需的软件

  1. 通过Ninject安装NuGet和“Ninject.MVC3”(也安装“Ninject.Web.Common”)。
  2. 通过SharpRepository安装NuGet,“SharpRepository for EF5”和“SharpRepository with Ninject IOC”。
  3. 定义存储库图层

    1. 创建DbContext derived class,例如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.
      }
      
    4. 定义消费者图层

      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;
            }
        }
        
      2. 通过依赖注入容器(DiC)Ninject设置依赖注入(DI)

        文件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一起运行起来!

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

        <击> 顺便说一句,我dbContextType属性添加到repository部分以使其正常工作(与Jeff T的答案形成对比)。


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