急切加载不适用于 BackgroundService
Eager loading doesn't work with BackgroundService
我正在尝试在运行 BackgroundService
的控制台应用程序中加载相关实体,
但它不加载相关实体,我已经遇到这个问题好几个小时了,我只是注意到它只发生在 BackgroundService
中,通过注入 DbContext [=] 在 Web 应用程序中尝试了相同的 DbContext
25=]在索引页面模型中,没有问题。
这是来自控制台应用程序的代码:
后台服务:
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//Jobs always empty!
var theBatch = _context.Batches.Include(x => x.Jobs).FirstOrDefault();
}
}
程序文件:
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
我正在使用 .NET 5 和 EF Core 5.0.12
你所拥有的应该像书面那样工作。因此,请仔细检查您的配置。正如@Nkosi 指出的那样,您应该使用更短的作用域,但是在 ExecuteAsync 中放置一个作用域是不够的,因为它 returns 的任务与 BackgroundService 实例具有相同的生命周期。
无论如何,这是一个在 .NET 6 中运行良好的完整重现。
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{ }
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public DbSet<Batch> Batches { get; set; }
public DbSet<Job> Jobs{ get; set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
}
public class Job
{
public int Id { get; set; }
}
public class Batch
{
public int Id { get; set; }
public virtual ICollection<Job> Jobs { get; set; } = new HashSet<Job>();
}
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var batch = new Batch();
batch.Jobs.Add(new Job() );
context.Batches.Add(batch);
context.SaveChanges();
context.ChangeTracker.Clear();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var theBatch = await _context.Batches.Include(x => x.Jobs).FirstOrDefaultAsync();
Console.WriteLine(theBatch.Jobs.Count);
}
}
好吧,我写这篇文章的时候我真的很生气在这个问题上花费的时间和精力,我不知道应该责怪谁,微软还是在 .NET 核心中安装 EF 6 的人项目。 Microsoft 很难找出问题的根源。
我使用的是来自 System.Data.Entity
命名空间的 Include
而不是 Microsoft.EntityFrameworkCore
纯属巧合,我无缘无故地使用了FirstOrDefaultAsync
,得到了这个奇怪的异常:
'The provider for the source IQueryable doesn't implement
IDbAsyncQueryProvider. Only providers that implement
IDbAsyncQueryProvider can be used for Entity Framework asynchronous
operations.
当我查看它时,我发现我为 FirstOrDefaultAsync
使用了错误的命名空间(System.Data.Entity
而不是 Microsoft.EntityFrameworkCore
)
当我更改名称空间时,一切正常!
我正在尝试在运行 BackgroundService
的控制台应用程序中加载相关实体,
但它不加载相关实体,我已经遇到这个问题好几个小时了,我只是注意到它只发生在 BackgroundService
中,通过注入 DbContext [=] 在 Web 应用程序中尝试了相同的 DbContext
25=]在索引页面模型中,没有问题。
这是来自控制台应用程序的代码:
后台服务:
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//Jobs always empty!
var theBatch = _context.Batches.Include(x => x.Jobs).FirstOrDefault();
}
}
程序文件:
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
我正在使用 .NET 5 和 EF Core 5.0.12
你所拥有的应该像书面那样工作。因此,请仔细检查您的配置。正如@Nkosi 指出的那样,您应该使用更短的作用域,但是在 ExecuteAsync 中放置一个作用域是不够的,因为它 returns 的任务与 BackgroundService 实例具有相同的生命周期。
无论如何,这是一个在 .NET 6 中运行良好的完整重现。
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
class Program
{
static async Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddLogging()
.AddDbContext<MyDbContext>(options => options
.UseSqlServer(context.Configuration.GetConnectionString("MyConnection")))
.AddHostedService<MyService>()
.BuildServiceProvider();
});
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{ }
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public DbSet<Batch> Batches { get; set; }
public DbSet<Job> Jobs{ get; set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
}
public class Job
{
public int Id { get; set; }
}
public class Batch
{
public int Id { get; set; }
public virtual ICollection<Job> Jobs { get; set; } = new HashSet<Job>();
}
public class MyService : BackgroundService
{
private readonly MyDbContext _context;
public MyService(MyDbContext context)
{
_context = context;
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var batch = new Batch();
batch.Jobs.Add(new Job() );
context.Batches.Add(batch);
context.SaveChanges();
context.ChangeTracker.Clear();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var theBatch = await _context.Batches.Include(x => x.Jobs).FirstOrDefaultAsync();
Console.WriteLine(theBatch.Jobs.Count);
}
}
好吧,我写这篇文章的时候我真的很生气在这个问题上花费的时间和精力,我不知道应该责怪谁,微软还是在 .NET 核心中安装 EF 6 的人项目。 Microsoft 很难找出问题的根源。
我使用的是来自 System.Data.Entity
命名空间的 Include
而不是 Microsoft.EntityFrameworkCore
纯属巧合,我无缘无故地使用了FirstOrDefaultAsync
,得到了这个奇怪的异常:
'The provider for the source IQueryable doesn't implement IDbAsyncQueryProvider. Only providers that implement IDbAsyncQueryProvider can be used for Entity Framework asynchronous operations.
当我查看它时,我发现我为 FirstOrDefaultAsync
使用了错误的命名空间(System.Data.Entity
而不是 Microsoft.EntityFrameworkCore
)
当我更改名称空间时,一切正常!