我在BackgroundServices中有一个方法可以成功地从API检索数据。但是,当将响应数据保存到dbContext时,我得到了错误:当identity_insert设置为OFF时,无法在表"Orders"中为标识列插入显式值。
//In Program.cs
builder.Services.AddHostedService<ConsumedScopeServiceHostedService>();
当我在Postman中测试API并且没有使用BackgroundServices时,SaveChangesAsync((起作用。有人能帮忙吗?
public class ConsumedScopeServiceHostedService : BackgroundService
{
public ConsumedScopeServiceHostedService
(
IServiceProvider services
)
{
Services = services;
}
public IServiceProvider Services { get; }
private readonly PeriodicTimer _importOrdersTimer = new PeriodicTimer(TimeSpan.FromMinutes(2));
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (await _importOrdersTimer.WaitForNextTickAsync(stoppingToken) && !stoppingToken.IsCancellationRequested)
{
await DoWorkAsync();
}
}
private async Task DoWorkAsync()
{
using (var scope = Services.CreateScope())
{
var scopedDbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
foreach (var item in newOrders)
{
scopedDbContext.Add(item);
}
scopedDbContext.SaveChanges();
}
}
}
根据错误,我认为您正在向Order
的Id
(PK字段(传递一个值。如果您已经启用了标识,并且正在从DB中自动递增值,则不能为"插入"场景传入ID字段的值。
如果确实需要从代码传递Id
,则必须使用以下命令在数据库中启用IDENTITY_INSERT
SET IDENTITY_INSERT TableName ON
编辑
将[DatabaseGenerated(DatabaseGeneratedOption.None)]
添加到主键列中。然后尝试添加事务范围,也如下
using var transaction = scopedDbContext.Database.BeginTransaction();
scopedDbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Orders ON;");
foreach (var item in newOrders)
{
scopedDbContext.Add(item);
}
scopedDbContext.SaveChanges();
scopedDbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Orders OFF");
transaction.Commit();
using var scope = _serviceScopeFactory.CreateScope();
var OrderScopeService = scope.ServiceProvider.GetService<IOrder>();
var DbContextScopeService = scope.ServiceProvider.GetService<MyDbContext>();
我不需要将此注释添加到实体密钥
[DatabaseGenerated(DatabaseGeneratedOption.None)]
最终编辑
using var scope = _serviceScopeFactory.CreateScope();
var OrderScopeService = scope.ServiceProvider.GetService<IOrder>();
var DbContextScopeService = scope.ServiceProvider.GetService<MyDbContext>();
foreach (var item in newOrders)
{
DbContextScopeService.Add(item);
}
DbContextScopeService.SaveChanges();