C# 有没有更好的方法将dbcontext添加到Asp.core MVC控制器?
在新的MVC核心中,似乎将上下文获取到控制器的标准方法是这样做C# 有没有更好的方法将dbcontext添加到Asp.core MVC控制器?,c#,asp.net-core,constructor,entity-framework-core,C#,Asp.net Core,Constructor,Entity Framework Core,在新的MVC核心中,似乎将上下文获取到控制器的标准方法是这样做 public class BaseController : Controller { public readonly ReportDBContext _db; public BaseController(ReportDBContext db) { _db = db; } } 然后我可以使用 public class HomeCont
public class BaseController : Controller
{
public readonly ReportDBContext _db;
public BaseController(ReportDBContext db)
{
_db = db;
}
}
然后我可以使用
public class HomeController : BaseController
{
public HomeController(ReportDBContext db) : base(db) { }
}
在所有其他控制器中使此操作更容易。
通常在Asp.net MVC中,我可以随时使用new ReportDBContext()
现在是否有类似的方法,或者我必须在asp.core MVC中的所有控制器中都有上下文
通常在Asp.net MVC中,我可以随时使用newReportDBContext
()获取上下文
现在,您也可以这样做,即在控制器中显式创建新上下文。除了最佳实践之外,没有任何东西可以阻止您这样做
使用依赖项注入的一些好处是,您可以在启动
类中定义依赖项的生存期,并在所有控制器中重用它,并且可以在单元测试中模拟依赖项。有关更多信息,请参阅和
但如果您不想或有理由不这样做,您当然不必使用依赖项注入。编译器不会强制您定义接受依赖项的自定义构造函数。ASP.NET核心的体系结构是基于依赖项注入构建的。它甚至有一个内置的依赖注入容器,但您也可以使用其他容器,如AutoFac或NInject。如果需要在多个操作中使用DbContext,可以使用构造函数注入,如示例中所示 如果只需要一次,可以将其直接注入action方法,如下所示:
public IActionResult Get([FromServices]ReportDbContext db)
{
…
}
依赖注入的使用使代码更易于测试。对于单元测试,您可以插入InMemory DbContext
在我看来,这比自己构建DbContext的工作量还要少。这是由框架完成的。感谢的回答,如果您决定使用依赖项注入,那么您可以按照下面提到的步骤操作
假设您定义了ReportDBContext
,如下所示:
public class ReportDBContext : DbContext
{
public DbSet<Sample> Samples { get; set; }
//...
public ReportDBContext(DbContextOptions<ReportDBContext> options) : base(options)
{
//...
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//...What needed
services.AddDbContext<ReportDBContext>(options => options.UseSqlServer("Connection string to your DB"));
//...What needed
}
//...
}
因此,您可以像这样轻松地将ReportDBContext
注入到类中(例如,将其注入到一个控制器中):
您可以简单地将ReportDBContext
注入到BaseController
中,而不是将它注入到项目中的每个控制器中
更新1
如果不想将ReportDBContext
注入每个构造函数,则可以使用HttpContext.RequestServices按如下方式设计BaseController
:
public class BaseController : Controller
{
protected ReportDBContext DbContext => (ReportDBContext)HttpContext.RequestServices.GetService(typeof(ReportDBContext));
//...
}
[Route("api/[controller]")]
public class ValuesController : BaseController
{
//...
[HttpGet]
public List<Sample> Get() => DbContext.Samples.ToList();
}
公共类BaseController:控制器
{
受保护的ReportDBContext=>(ReportDBContext)HttpContext.RequestServices.GetService(typeof(ReportDBContext));
//...
}
[路由(“api/[控制器]”)]
公共类值控制器:BaseController
{
//...
[HttpGet]
public List Get()=>DbContext.Samples.ToList();
}
请在此处阅读更多信息:
您还需要至少安装这两个NuGet软件包:
似乎您不了解依赖注入的好处。DI对于编写灵活且易于维护的软件非常重要。没有理由不使用它。我建议你通过观看来了解DI及其好处。谢谢,这正是我现在所了解的——我只是想知道是否有更好的方法。看起来你最终会有20个左右的控制器,每个控制器都有一个接受DBContext的构造函数。@RichardHousham我在回答的最后说,你可以将DBContext注入BaseController,而不是注入每个控制器:-)是的,但是这仍然需要你的普通控制器仍然在构造函数中有它,即public HomeController(ReportDBContext db):base(db){}或者还有其他方法吗?@RichardHousham我已经更新了答案,现在它涵盖了你的需求,这很有趣,如果我有2个上下文,但在少数地方可能只使用1个,那么我可以使用这个吗?@RichardHousham是的,应该可以。只要两个上下文都已注册
public class BaseController : Controller
{
protected ReportDBContext DbContext => (ReportDBContext)HttpContext.RequestServices.GetService(typeof(ReportDBContext));
//...
}
[Route("api/[controller]")]
public class ValuesController : BaseController
{
//...
[HttpGet]
public List<Sample> Get() => DbContext.Samples.ToList();
}