Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有更好的方法将dbcontext添加到Asp.core MVC控制器?_C#_Asp.net Core_Constructor_Entity Framework Core - Fatal编程技术网

C# 有没有更好的方法将dbcontext添加到Asp.core 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

在新的MVC核心中,似乎将上下文获取到控制器的标准方法是这样做

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软件包:

  • (如果数据库提供程序是Microsoft SQL Server)

  • 似乎您不了解依赖注入的好处。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();
    }