首页 > 解决方案 > 使用数据库上下文的依赖注入。如何在普通类中获取数据库上下文

问题描述

我在启动方法中使用数据库上下文配置了我的 .net-core 2.1 服务。

 services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString(nameof(DatabaseContext))));

现在我可以执行以下操作来在我的控制器中获取我的数据库上下文:

var context = serviceProvider.GetService<DatabaseContext>();

这很好用。但是我怎么能在一个普通的类中访问数据库上下文,像这样可以做到:

public class MyAccessClass{

    public MyAccessClass(){

        //Access the ServiceProvider or get the Database-Context class anywhere else
    }
}

我不想通过构造函数传递数据库上下文对象或再次初始化 DatbaseContext 类。

谢谢你的帮助。

标签: asp.net-coreentity-framework-core

解决方案


您应该通过构造函数获取依赖项,最好是接口,例如IDatabaseContext,但下面的代码示例基于您的代码。如果您添加MyAccessClass为服务,例如services.AddTransient<MyAccessClass>(),然后在控制器中使用依赖注入,则数据库上下文将由 ASP.NET Core 中的默认 IoC 容器自动注入到构造函数中。

您不应该依赖它IServiceProvider,原因是您的类不希望对实现做出假设,它只需要数据库上下文。让它依赖IServiceProvider会假设这个上下文以及任何可能的未来依赖项来自 ASP.NET Core 中的 IoC,但情况可能并非如此(如果你只是想稍后将它作为类库发布呢?)。这将使MyAccessClass该类难以在控制器之外进行测试和使用。

你在评论中说:

“...或在其他任何地方获取 Database-Context 类”

通过简单地将上下文接受到构造函数中,其他任何地方都是完全灵活的,因为您的类不知道其他任何地方在哪里,但是创建您的类的任何东西都知道!

ASP.NET Core 中的 DI 示例

通过构造函数将上下文作为依赖

public class MyAccessClass{
    private readonly DatabaseContext databaseContext;
    public MyAccessClass(DatabaseContext databaseContext) {
        this.databaseContext = databaseContext;
    }
}

添加为服务

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<MyAccessClass>();
}

注入控制器

public class MyController : Controller
{
    private readonly MyAccessClass myAccessClass;
    //Happily injected through DI
    public MyController(MyAccessClass myAccessClass)
    {
        this.myAccessClass = myAccessClass;
    }
}

或者直接注入一个动作

public class MyController : Controller
{
    public MyController()
    {
    }

     public IActionResult MyAction([FromServices] MyAccessClass myAccessClass)
     {

     }
}

推荐阅读