【问题标题】:Injecting DbContext to class library project in same Asp.Net Core 2 solution在同一个 Asp.Net Core 2 解决方案中将 DbContext 注入类库项目
【发布时间】:2018-05-18 12:59:24
【问题描述】:

过去相对容易的事情,现在已经不那么容易了。在我搜索过的几十次中,我很少找到这种情况的答案,我无法相信这种情况在大多数项目结构中普遍存在。

我有一个标准的 Core 2.0 Web 应用程序,现在,为了简单起见,我有一个基础设施项目和一个单元测试项目。由于测试项目不运行 asp.net,因此我对如何完成测试场景有一个很好的想法,而且我有一个很棒的视频教程来说明如何完成它。

问题在于在我的基础设施项目中访问 DbContext。 (.Net Core 类库)

DbContext 在 Startup 中设置得非常好

var connString = Configuration.GetSection("ApplicationConfiguration:ConnectionStrings:DefaultConnection").Value;
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connString));

在控制器中我可以访问它

private ApplicationDbContext _context;
private IConfiguration Configuration { get; set; }

public HomeController(IConfiguration configuration, ApplicationDbContext context)
{
    _context = context;
    Configuration = configuration;
}

public IActionResult Index()
{
     // gets users from the DI injected context in the controller
    var users = _context.AppUsers.ToList();

    // if GetUsers is defined statically, this doesn't work because the injected context is always null
    //var diUsers = DatabaseService.GetUsers():

    // making it non-static and newing it up works, but defeats the purpose because you are passing the context, asp.net is not injecting it
    var ds = new DatabaseService(_context);
    var diUsers = ds.GetUsers();

    var svm = SettingsViewModel();

    return View(svm);
}

数据库服务

private ApplicationDbContext _context;
//this is the constructor for DatabaseService class
public DatabaseService(ApplicationDbContext context)
{
    _context = context;
}

public List<ApplicationUser> GetUsers()
{
    var users = _context.AppUsers.ToList();
    return users;
}

是的,我知道我应该使用存储库,一旦我弄清楚了这一点,我就会这样做。如何在 Infrastructure 项目中设置我的类,以便在启动时创建注入的 DbContext 而不必将其作为参数传递。

附录:

使用 Nkosi 提供的答案,我可以在控制器中注入数据服务并使用它。

但如果我有一个单独的基础设施项目(Asp.net core 2 类库),它实现了我的存储库和 UoW

 public class GenericRepository<T> : IRepository<T> where T : class
{
    public GenericRepository()
    {

    }
    //rest of code removed
}

我怎样才能在那里注入 DbContext?我是否需要创建一个接口 IDbContext 来包装 DbContext,并在启动时注册它?

【问题讨论】:

  • 只需注册 DatabaseService 并将其注入控制器。框架将处理服务的解析
  • 你的DatabaseService 看起来就像一个存储库......你已经明白了,哈哈

标签: c# dependency-injection entity-framework-core asp.net-core-2.0


【解决方案1】:

假设您的服务有以下内容

public interface IDatabaseService {
    List<ApplicationUser> GetUsers();
    //...
}

public class DatabaseService : IDatabaseService {

    public DatabaseService(ApplicationDbContext context) {
        //...code removed for brevity
    }

    //...code removed for brevity
}

服务显式依赖ApplicationDbContext,当从服务容器解析实现时将注入该ApplicationDbContext

Startup.ConfigureServices注册服务

var connString = Configuration.GetSection("ApplicationConfiguration:ConnectionStrings:DefaultConnection").Value;
services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(connString));
services.AddScoped<IDatabaseService, DatabaseService>();

并重构控制器以显式依赖服务

private IDatabaseService ds;
private IConfiguration Configuration { get; set; }

public HomeController(IConfiguration configuration, IDatabaseService ds) {
    this.ds = ds;
    Configuration = configuration;
}

public IActionResult Index() {
    var diUsers = ds.GetUsers();

    var svm = SettingsViewModel();

    return View(svm);
}

【讨论】:

  • @Nkosi ...我看到了如何做到这一点,但对实际注入 DbContext 感到困惑。谢谢你澄清这一点。现在,如果我创建另一个也将使用 DatabaseService 的类库项目呢?如何在那里注入 DbContext?在您的回答中,似乎注入能力总是与网络应用程序耦合
  • @dinotom 在这种情况下,代码与ApplicationDbContext 耦合,这是一个主要与视图(Web 项目)相关的实现问题,但如果您将其抽象出来并在其他项目中使用抽象那么它就不再重要了。依赖类将依赖于将在运行时实现/解析的抽象。
  • @dinotom 我建议你不要让你的代码过于依赖 DbContext 而是依赖于包装它的服务。 DbContext 是一个实现问题。
  • @Nkosi ...您介意看一下我的问题的附录吗?泰
  • @dinotom 你基本上用那个加强了我的最后两个 cmets。
猜你喜欢
  • 2021-04-19
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多