急切加载不适用于 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) 当我更改名称空间时,一切正常!