如何在 EF 核中实例化 DbContext

我有 setup.net 核心项目和 db 上下文。但我不能开始使用 dbContext,但由于这个错误-

”没有任何论点符合规定的形式 参数‘选项’”

总监:

public IActionResult Index()
{
using (var db = new BlexzWebDb())
{


}
return View();
}

Dbcontext 代码:

public class BlexzWebDb : DbContext
{
public BlexzWebDb(DbContextOptions<BlexzWebDb> options)
: base(options)
{ }


public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<AssignedRole> AssignedRoles { get; set; }


}

错误图片附后。什么是可能的修复该问题? 先谢谢你

pic

92872 次浏览

注意


在写这篇文章的时候,使用依赖注入框架的 EF Core 还没有像现在这样广为人知。这个答案从 DI 的角度给出了问题的答案,这在当时有助于 OP。

另一个答案提供了使用 new运算符实例化 DbContext 的传统方法。


TL; DR,3个选项:

选择一

在应用程序配置期间注册 DbContext:

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextPool<BlexzWebDb>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BlexzWebConnection")));
}

并使用 DI 框架检索它:

public class SomeController : Controller
{
private readonly BlexzWebDb _db;


//the framework handles this
public SomeController(BlexzWebDb db)
{
_db = db;
}
}

选择二

如果您正在寻找使用 IOptions<OperationalStoreOptions>的设计时 IdentityDbContext,请参见: 从另一个项目-EF 核心为 ApiAuthorizationDbContext 添加迁移

选择三

或者使用 new操作符并提供详细信息,详细信息见@Qamar Zaman 的回答。


答案很长,还有为什么 DI 是一种享受

在 EF Core 中,通常会向构造函数传递一些 DbContextOptions。

一般来说,构造函数是这样的:

public BlexzWebDb(DbContextOptions<BlexzWebDb> options) : base(options)

如您所见,没有无参数构造函数形式的有效重载:

因此,这是行不通的:

using (var db = new BlexzWebDb())

显然,您可以在构造函数中传入一个 Option对象,但是还有一个替代方案,

相反


.Net Core has IoC implemented in it's roots. Okay, this means; you don't create a context, you ask the framework to give you one, based on some rules you defined before.

示例: 在某个地方注册 dbcontext,(Startup.cs) :

//typical configuration part of .net core
public void ConfigureServices(IServiceCollection services)
{
//some mvc
services.AddMvc();
  

//hey, options!
services.AddDbContextPool<BlexzWebDb>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BlexzWebConnection")));
//...etc

现在注册部分已经完成,您可以从框架中检索上下文。例如: 控制反转通过控制器中的构造函数:

public class SomeController : Controller
{
private readonly BlexzWebDb _db;


//the framework handles this
public SomeController(BlexzWebDb db)
{
_db = db;
}


//etc.

为什么?

那么,为什么不提供参数和 new呢?

使用 new并没有什么错——有很多情况下它的工作效果最好。

但是,控制反转被认为是一个很好的实践。在执行 asp dotnet core时,您可能会经常使用它,因为大多数库都提供了使用它的扩展方法。如果你不熟悉它,并且你的研究允许它; 你一定应该尝试一下。

因此,我不提供 “只是一种实例化的方法”对象,而是尝试让您进入这个轨道——使用框架内联。这样你以后就不用麻烦了。此外,否则 “使用激活器的 CreateInstance”将只是作为一个有效的答案; -)

有关连结:

作为@Stefan 回答的补充,还有另一种方法来实现这一点。您可以在 DbContext 类的 OnConfiguration 方法中设置 db 连接字符串,而无需在 startup.cs 中添加 DbContext 服务。

设置

public static class Setting
{
public static string ConnectionString { get; set; }
}

Startup.cs

Setting.ConnectionString = Configuration.GetSection("ConnectionStrings:BlexzDbConnection").Value;

BlexzWebDb.cs

public class BlexzWebDb : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(Setting.ConnectionString);
}
}
}

Homecontroller.cs

public class HomeController : Controller
{
private readonly BlexzWebDb db;


public HomeController()
{
this.db = new BlexzWebDb();
}


//etc.

从 ConnectionString 实例化 DbContext 的新对象

var connectionstring = "Connection string";


var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(connectionstring);




ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options);


// Or you can also instantiate inside using


using(ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options))
{
//...do stuff
}

EF Core 3.1的代码示例:

public class Test
{
private readonly IServiceProvider _serviceProvider;


public Test(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}


public async Task<RequestResult> Handle(...)
{
await using var context = CreateContext();
...
}


private DocumentContext CreateContext()
{
var options = _serviceProvider.GetService<IOptions<DocumentContextOptions>>();
return new DocumentContext(options);
}
}