简体   繁体   English

使用存储库模式实现依赖注入的混淆-C#EF Core

[英]Confusion implementing Dependency Injection with a repository pattern - c# EF Core

I'm moving the data access portion of a project to a WebAPI and using Entity Framework Core to do what EF does. 我正在将项目的数据访问部分移至WebAPI,并使用Entity Framework Core来执行EF的工作。

I know that the preferred pattern is to now rely on dependency injection to create the dbContext when "the controller" is used. 我知道首选模式是现在使用“控制器”时依赖于依赖项注入来创建dbContext。 The "Hello, World!" “你好,世界!” tutorials show examples of accessing the context by the following: 教程显示了通过以下方式访问上下文的示例:

    private BloggingContext _context;

    public BlogsController(BloggingContext context)
    {
        _context = context;
    }

The issue that I'm having is I need to go one layer up...as I have a "Service" interface that exposes the methods of the repository. 我遇到的问题是我需要向上一层...因为我有一个“服务”接口,可以显示存储库的方法。

I tried putting the context instantiation into my repository, but, of course, then when I tried to new up an instance of the service, it was requiring a context object to be passed in. I tried to resolve it by sending in a new BloggingContext() as the context parameter, but received the error: No database provider has been configured for this DbContext. 我尝试将上下文实例化放入我的存储库中,但是,当我尝试建立服务实例时,它要求传递一个上下文对象。我尝试通过发送新的BloggingContext来解决该问题。 ()作为上下文参数,但收到错误: No database provider has been configured for this DbContext. Which, of course, makes sense because the new one that I was passing in didn't have a connection to the database associated with it. 这当然是有道理的,因为我传入的new数据库没有与之关联的数据库的连接。 That connection is defined in the Startup.cs as described in the various tutorials I'm following trying to cut my teeth on this transition. 该连接是在Startup.cs中定义的,正如我在尝试通过这种过渡切入的各种教程中所描述的那样。

So, given the following code in my controller, how can I invoke the service and still let the Dependency Injection do what it's designed to do at the repository level? 因此,给定控制器中的以下代码,我如何才能调用该服务,并仍然让依赖注入执行其在存储库级别上要执行的操作?

    [HttpGet("{bool}")]
    public IActionResult GetRoleNames(bool? isActive)
    {
        var service = new SecurityService();
        try
        {
            return Ok(service.GetRoleNames(isActive));
        }
        catch (Exception ex)
        {
            Log.Error("Failed to get list of role names from the API", ex.Message);
            return BadRequest(ex);
        }
    }

I'm pretty sure I have the [HttpGet("{bool}")] a bit FUBARd as well since GetRoleNames will permit NULL, but I'll cross that bridge after resolving the DI issue. 我很确定我也有[HttpGet("{bool}")]有点FUBARd,因为GetRoleNames允许NULL,但是在解决DI问题之后,我将跨越GetRoleNames桥梁。

Use Dependency Injection to create your service (I like to have an interface)- 使用依赖注入创建您的服务(我喜欢有一个接口)-

private readonly ISecurityService _service;

public BlogsController(ISecurityService service)
{
    _service = service;
}

Call your method using the constructed service 使用构造的服务调用方法

[HttpGet("{bool}")]
public IActionResult GetRoleNames(bool? isActive)
{
    try
    {
        return Ok(_service.GetRoleNames(isActive));
    }
    catch (Exception ex)
    {
        Log.Error("Failed to get list of role names from the API", ex.Message);
        return BadRequest(ex);
    }
}

Your security service can have the context injected 您的安全服务可以注入上下文

private readonly BloggingContext _context;

public class SecurityService : ISecurityService
{
    public SecurityService (BloggingContext context)
    {
        _context = context
    }
}

You can register your service in Startup.cs in the ConfigureServices method: 您可以使用ConfigureServices方法在Startup.cs中注册服务:

service.AddScoped<ISecurityService, SercurityService>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM