EF Core:通过将注入的 DbContext 对象作为参数传递来创建对象
EF Core: Create an object by passing an injected DbContext object as parameter
我已经创建了一个 .Net Core MVC 项目并了解依赖注入如何为我们的 MVC 控制器工作,如下所示,但就像我想通过调用同样注入 interface/class 作为参数。
public class ShiftsController : BaseController
{
ShardingDbContext _dbContext;
public ShiftsController(ShardingDbContext ShardingDbContext) : base(ShardingDbContext)
{
_dbContext = ShardingDbContext;
ViewBag.Menu = BuildMenu();
}
我已经将 DbContext 注入到我的 Startup.cs 文件中,如下所示,
//Entity Framework Core
services.AddDbContext<ShardingDbContext>(options => options.UseSqlServer(ConnectionString),
ServiceLifetime.Transient);
ShiftsController 是一个 C#-MVC 控制器,当我 运行 我的应用程序并转到我的应用程序中的 Shift 页面时,DbContext 工作正常,但是当我尝试下面给出的代码时,它不起作用并给出错误。所以我不知道如何在使用“new”关键字创建对象时传递已注册的class的对象。
public class JobScheduler
{
ShardingDbContext _dbContext;
public JobScheduler(ShardingDbContext ShardingDbContext)
{
_dbContext = ShardingDbContext;
}...
这是我自己的 class 并尝试为 class JobScheduler 创建一个对象,如下所示。
JobScheduler jobs = new JobScheduler();
所以现在我不知道如何将 EF 核心的 DbContext 对象传递给构造函数 JobScheduler,DI 对于控制器工作正常但对于普通 class。任何人都可以帮助解决这个问题吗?我也热切地等待着理解这个逻辑?
你是对的:你的 DI 工作正常但你的 ShardingDbContext
没有传递到你的 JobScheduler
因为你没有使用 DI 来实例化 JobScheduler
。每当您使用 new
关键字显式创建对象实例时,您都没有使用 DI.
您有两个选择:
- 无论你在哪里调用
new JobScheduler()
让 DI 通过构造函数给你注入一个 ShardingDbContext
并像这样将它传递给 JobScheduler new JobScheduler(shardingDbContext)
- 也将
JobScheduler
注册到依赖注入,让 DI 构建整个链,这样你就不需要调用 new JobScheduler()
而是直接在任何地方注入 JobScheduler
你需要它
编辑
此处要求的是使用短暂数据库上下文的定时作业示例:
public class TimedBackgroundService : IHostedService, IDisposable
{
private readonly Timer timer;
private readonly IServiceProvider serviceProvider;
public TimedBackgroundService(IServiceProvider serviceProvider)
{
timer = new Timer(async state => await ExecuteAsync());
this.serviceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken stoppingToken)
{
timer.Change(0, TimeSpan.FromMinutes(30));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken stoppingToken)
{
timer.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose() => timer.Dispose();
private async Task ExecuteAsync()
{
try
{
using var scope = serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetRequiredService<MyJob>();
await job.Execute();
}
catch (Exception exception)
{
// log error here
return;
}
}
}
MyJob
class 看起来像这样:
public class MyJob
{
private readonly ShardingDbContext dbContext;
public MyJob(ShardingDbContext dbContext)
{
this.dbContext = dbContext;
}
public Task Execute()
{
// Your logic goes here
}
}
然后你像这样在启动中注册你的 classes:
services
.AddHostedService<TimedBackgroundService>()
.AddScoped<MyJob>();
现在您有一个每 30 分钟运行一次并使用短期数据库上下文的作业。
像这样注册您的 JobScheculer:
services.AddSingleton<JobScheduler>();
然后像这样使用您的 dbContext:
public class JobScheduler
{
private readonly IServiceProvider provider;
public JobScheduler(IServiceProvider provider)
{
}...
public (or private etc) DoYourJob()
{
using (var scope = provider.CreateScope())
{
var dbContext = scope.GetService<ShardingDbContext>();
//use it here
}
}
在 Startup.cs class 的 ConfigureServices 方法的末尾,我没有更改 JobSchedulerclass 中的任何内容并从服务提供商传递 DbContext 对象,如图所示下面,感谢所有试图帮助解决这个问题的人。
public void ConfigureServices(IServiceCollection services)
{
...
...
JobScheduler job = new
JobScheduler(services.BuildServiceProvider().CreateScope().ServiceProvider
.GetService<ShardingDbContext>());
job.Start();
}
我已经创建了一个 .Net Core MVC 项目并了解依赖注入如何为我们的 MVC 控制器工作,如下所示,但就像我想通过调用同样注入 interface/class 作为参数。
public class ShiftsController : BaseController
{
ShardingDbContext _dbContext;
public ShiftsController(ShardingDbContext ShardingDbContext) : base(ShardingDbContext)
{
_dbContext = ShardingDbContext;
ViewBag.Menu = BuildMenu();
}
我已经将 DbContext 注入到我的 Startup.cs 文件中,如下所示,
//Entity Framework Core
services.AddDbContext<ShardingDbContext>(options => options.UseSqlServer(ConnectionString),
ServiceLifetime.Transient);
ShiftsController 是一个 C#-MVC 控制器,当我 运行 我的应用程序并转到我的应用程序中的 Shift 页面时,DbContext 工作正常,但是当我尝试下面给出的代码时,它不起作用并给出错误。所以我不知道如何在使用“new”关键字创建对象时传递已注册的class的对象。
public class JobScheduler
{
ShardingDbContext _dbContext;
public JobScheduler(ShardingDbContext ShardingDbContext)
{
_dbContext = ShardingDbContext;
}...
这是我自己的 class 并尝试为 class JobScheduler 创建一个对象,如下所示。
JobScheduler jobs = new JobScheduler();
所以现在我不知道如何将 EF 核心的 DbContext 对象传递给构造函数 JobScheduler,DI 对于控制器工作正常但对于普通 class。任何人都可以帮助解决这个问题吗?我也热切地等待着理解这个逻辑?
你是对的:你的 DI 工作正常但你的 ShardingDbContext
没有传递到你的 JobScheduler
因为你没有使用 DI 来实例化 JobScheduler
。每当您使用 new
关键字显式创建对象实例时,您都没有使用 DI.
您有两个选择:
- 无论你在哪里调用
new JobScheduler()
让 DI 通过构造函数给你注入一个ShardingDbContext
并像这样将它传递给 JobSchedulernew JobScheduler(shardingDbContext)
- 也将
JobScheduler
注册到依赖注入,让 DI 构建整个链,这样你就不需要调用new JobScheduler()
而是直接在任何地方注入JobScheduler
你需要它
编辑
此处要求的是使用短暂数据库上下文的定时作业示例:
public class TimedBackgroundService : IHostedService, IDisposable
{
private readonly Timer timer;
private readonly IServiceProvider serviceProvider;
public TimedBackgroundService(IServiceProvider serviceProvider)
{
timer = new Timer(async state => await ExecuteAsync());
this.serviceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken stoppingToken)
{
timer.Change(0, TimeSpan.FromMinutes(30));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken stoppingToken)
{
timer.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose() => timer.Dispose();
private async Task ExecuteAsync()
{
try
{
using var scope = serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetRequiredService<MyJob>();
await job.Execute();
}
catch (Exception exception)
{
// log error here
return;
}
}
}
MyJob
class 看起来像这样:
public class MyJob
{
private readonly ShardingDbContext dbContext;
public MyJob(ShardingDbContext dbContext)
{
this.dbContext = dbContext;
}
public Task Execute()
{
// Your logic goes here
}
}
然后你像这样在启动中注册你的 classes:
services
.AddHostedService<TimedBackgroundService>()
.AddScoped<MyJob>();
现在您有一个每 30 分钟运行一次并使用短期数据库上下文的作业。
像这样注册您的 JobScheculer:
services.AddSingleton<JobScheduler>();
然后像这样使用您的 dbContext:
public class JobScheduler
{
private readonly IServiceProvider provider;
public JobScheduler(IServiceProvider provider)
{
}...
public (or private etc) DoYourJob()
{
using (var scope = provider.CreateScope())
{
var dbContext = scope.GetService<ShardingDbContext>();
//use it here
}
}
在 Startup.cs class 的 ConfigureServices 方法的末尾,我没有更改 JobSchedulerclass 中的任何内容并从服务提供商传递 DbContext 对象,如图所示下面,感谢所有试图帮助解决这个问题的人。
public void ConfigureServices(IServiceCollection services)
{
...
...
JobScheduler job = new
JobScheduler(services.BuildServiceProvider().CreateScope().ServiceProvider
.GetService<ShardingDbContext>());
job.Start();
}