数据库
首页 > 数据库> > 避免将具体的数据库上下文类注入控制器

避免将具体的数据库上下文类注入控制器

作者:互联网

我将Entity Framework Core for MySql与数据库优先方法结合使用.

搭建好数据库后,它会生成上下文类:sakilaContext.cs(sakila是MySql中的内置数据库/方案,我用它来玩耍).

我将数据库注入了Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        var connectionString = @"server=localhost;port=1123;user=root;password=xxx;database=sakila";
        services.AddDbContext<sakilaContext>(options => options.UseMySql(connectionString));
    }

在我的api控制器中,我这样做如下:

private sakilaContext dbCtx;

public SakilaController(sakilaContext dbContext)
{
    dbCtx = dbContext;
}

只是个小疑问,

>在这种情况下注入具体实现是错误的吗?
>如果是这样,我怎么能只注入一个接口而不是注入一个具体的实现?

谢谢

解决方法:

is it wrong to inject a concrete implementation in this case??

这取决于.如果您正在编写具有不同关注点(业务逻辑,验证,授权)的多层应用程序,或者您正在编写一个5页的应用程序以显示有限数量的用户的杂项信息?

对于小型应用程序(大多数为只读应用程序),我确实做到了这一点,因为只有很小的更改,而我不需要Over design and architect the solution.

If it is, how can I just inject an interface rather than inject a concrete implementation?

当然可以,但是在某个时候,一个类将需要一个dbcontext,它可以由需要它的对象进行DI或创建.如果确实将数据访问抽象到单独的类/接口中,则我不建议使用DI(将上下文注入到具体的数据访问中),因为具体的类型将紧密地与EF耦合.这意味着,如果您决定切换到Dapper,NHibernate或其他ORM,则无论如何都必须重写所有方法.

快速而肮脏的方式(对于小型/学习型体验,我永远不会推荐给数百万个用户系统使用)抽象DbContext的方法很简单:

public interface IUserDA
{
  IQueryable<User> Users { get; }
}

public class MyDbContext : IUserDA
{
  public DbSet<User> Users { get; set; }

  IQueryable<User> IUserDA.Users
  {
     get
     {
        return Users;  // references the DbSet
     }
  }

}

现在,您的MyDbContext实现了一个未与实体框架耦合的接口.

But if we inject a concrete class, does it defeat the DI purpose?

取决于您的目的.您到底想通过使用DI实现什么?您实际上是要编写真实的单元测试吗?您是否诚实地看到自己正在更改或具有多个安装/租户的接口的多个实例?

标签:asp-net-core-mvc,entity-framework-core,dependency-injection,c
来源: https://codeday.me/bug/20191108/2005931.html