C# 如何将实体框架 DbContext 注入 SharpRepository 的 ConfigurationBasedRepository

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16172448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 00:15:17  来源:igfitidea点击:

How-to inject the Entity Framework DbContext into the ConfigurationBasedRepository of SharpRepository

c#entity-frameworkrepositoryninjectsharp-repository

提问by Florian Wolters

I really would like to use SharpRepositorytogether with Ninject, but I do not understand how to configure Ninject to share the Entity Framework DbContext between the repositories.

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

I am using Entity Framework version 5 and Ninject version 3.

我正在使用实体框架版本 5 和 Ninject 版本 3。

Currently I am using Ef5Repositoryin my source code, but I want to replace it with ConfigurationBasedRepository. But I cannot figure out how to pass (or inject) the EF DbContextto the repositories.

目前我Ef5Repository在我的源代码中使用,但我想用ConfigurationBasedRepository. 但我无法弄清楚如何将 EF 传递(或注入)DbContext到存储库。

Example (current state):

示例(当前状态):

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)
    {
    }

    // [...]
}

Goal:

目标:

using SharpRepository.Repository;

public interface IProductRepository : IRepository<Product>
{
}

public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
    // [...]
}

I've already read the two blog posts SharpRepository: Getting Startedand SharpRepository: Configuration, but they both do not help me, since:

我已经阅读了两篇博客文章SharpRepository: Getting StartedSharpRepository: Configuration,但它们都没有帮助我,因为:

  1. The used DIC is StructureMap, not Ninject.
  2. The source code examples are incomplete (e.g. usage of not declared variables).
  1. 使用的 DIC 是 StructureMap,而不是 Ninject。
  2. 源代码示例不完整(例如使用未声明的变量)。

So my question: Can someone provide me with some source code example how-to to achieve the goal described above (sharing one Entity Framework DbContextinstance between all repositories extending ConfigurationBasedRepository)?

所以我的问题是:有人可以向我提供一些源代码示例如何实现上述目标(DbContext在扩展的所有存储库之间共享一个实体框架实例ConfigurationBasedRepository)?

采纳答案by Jeff Treuting

First, you will need to install the SharpRepository.Ioc.Ninject NuGet package. There are extension methods in here for hooking up Ninject to handle the loading a generic repository and setting the dependency resolver that SharpRepository uses.

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

Where ever you are setting up your Ninject binding rules (all the calls to kernel.Bind<>), you will need to add:

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

kernel.BindSharpRepository();

Next, in your Global.asax, or App_Start code, or your Bootstrapper logic (where ever you are calling application startup code) you will need to add the following:

接下来,在您的 Global.asax 或 App_Start 代码或 Bootstrapper 逻辑(无论您在哪里调用应用程序启动代码)中,您都需要添加以下内容:

// kernel is the specific kernel that you are setting up all the binding for
RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));

This will tell SharpRepository to use this Ninject Kernel when getting a new DbContext.

这将告诉 SharpRepository 在获取新的 DbContext 时使用此 Ninject 内核。

The last thing to do is to setup the rules for binding for the DbContext itself. If you are in a web application you will most likely want the scope of the DbContext to be per request. I personally don't use Ninject but I found this reference for using InRequestScope. I believe your code would look something like this:

最后要做的是为 DbContext 本身设置绑定规则。如果您在 Web 应用程序中,您很可能希望 DbContext 的范围是每个请求。我个人不使用 Ninject,但我找到了使用InRequestScope 的参考。我相信你的代码看起来像这样:

kernel.Bind<DbContext>().To<MyCustomEfContext>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["MyCustomEfContext"].ConnectionString);

Most people won't need this next piece but if you have custom logic in your CustomEfContext (I have an override for logging on calls to SaveChanges() for example), then you'll need to define your custom context type in the configuration file like so:

大多数人不需要下一部分,但是如果您的 CustomEfContext 中有自定义逻辑(例如,我有一个覆盖对 SaveChanges() 调用的登录),那么您需要在配置文件中定义自定义上下文类型像这样:

<repositories>
  <repository name="ef5Repository" connectionString="CustomEfContext" cachingStrategy="standardCachingStrategy" dbContextType="My.Data.CustomEfContext, My.Data" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" />
</repositories>

Where dbContextType defines the type of the custom DbContext you are using using the full type, namespace syntax. If you do this then you'll need to set Ninject to Bind on the custom context by changing .Bind<DbContext>() to .Bind<CustomEfContext>(). But like I said normally you can use DbContext directly without an issue.

其中 dbContextType 使用完整类型命名空间语法定义您正在使用的自定义 DbContext 的类型。如果您这样做,那么您需要通过将 .Bind<DbContext>() 更改为 .Bind<CustomEfContext>() 将 Ninject 设置为在自定义上下文上绑定。但是就像我通常所说的那样,您可以直接使用 DbContext 没有问题。

回答by Florian Wolters

First of all, the solution provided in the answer by Jeff T works!

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

I will conclude the steps I took to make Ninjectwork in a ASP.NET MVC 4 + EF 5 project. It is important to mention that the Specific Repositorypattern is implemented via SharpRepositoryin the following example.

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



Required software

所需软件

  1. Install Ninjectand "Ninject.MVC3" (which also installs "Ninject.Web.Common") via NuGet.
  2. Install SharpRepository, "SharpRepository for EF5" and "SharpRepository with Ninject IOC" via NuGet.
  1. 通过NuGet安装Ninject和“Ninject.MVC3”(也安装“Ninject.Web.Common”)。
  2. 通过NuGet安装SharpRepository、“SharpRepository for EF5”和“SharpRepository with Ninject IOC” 。

Define the Repositorylayer

定义存储库

  1. Create a DbContext derived class, e.g. Domain.EfContext. It is the

    "recommended way to work with context".

    • Declare all required DbSet<T>as public properties, e.g. public DbSet<Product> Products { get; set; }
    • Declare the following two constructors in the class Domain.EfContext:

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

  2. Define an interface for the Specific Repository, e.g.:

    // 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. Define a class which is implementing the Specific Repositoryand inherits from SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>, e.g.:

    public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
    {
        // TODO Implement domain specific logic here.
    }
    
  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.
    }
    

Define the Consumerlayer

定义消费者

  1. Create a Controller, e.g. 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;
        }
    }
    
  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;
        }
    }
    

Set up Dependency Injection (DI) via the Dependency Injection Container (DiC) Ninject

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

The file App_Start/NinjectWebCommon.csis automatically created by Ninject.Web.Common and we can load our modules and register our services in the method RegisterServices(IKernel kernel) : voidof the class NinjectWebCommon. Here is the complete source code of that method for the example:

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

Define the following sharpRepositorysection in the Web.config:

在 中定义以下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>

In addition, the connectionStringssection to make the example complete (I am using SQL Server LocalDB).

此外,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>


I hope that this conclusion helps other people to get ASP.NET MVC 4 together with Entity Framework 5 and SharpRepository up and running!

我希望这个结论可以帮助其他人将 ASP.NET MVC 4 与 Entity Framework 5 和 SharpRepository 一起启动并运行!

Please leave me a reply if I took one or more unnecessary steps or if you see possibilities to improve the architecture described in the example.

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

Btw, I hadto add the dbContextTypeattribute to the repositorysection to make it work (in contrast to the answer of Jeff T).

顺便说一句,我必须dbContextType属性添加到该repository部分才能使其工作(与 Jeff T 的答案相反)。



EDIT (2013-08-28):Striked out unnecessary steps (not required with the latest version of SharpRepository).

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