使用 DI 访问 Startup.cs 中的 NPGSQL

Accessing NPGSQL in Startup.cs using DI

使用 .NET Core 2.1、NPGSQL、Entity Framework 和 Linux。

从 Startups.cs' 配置函数,我在注入的依赖项 class 中调用一个函数,该函数又调用另一个注入的依赖项 class ,它使用 [=52= 访问数据库] + NPGSQL.

配置服务:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFrameworkNpgsql()
        .AddDbContext<MMContext>(options => options.UseNpgsql($"Host='localhost'; Port=1234;Database='mydb';Username='test';Password='test'"))
        .BuildServiceProvider();
        services.AddTransient<IMusicManager, MusicManager>();
        services.AddTransient<IMusicRepo, MusicRepo>();

      services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

配置函数:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc();

        using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
        {
            var mm = scope.ServiceProvider.GetRequiredService<IMusicManager>();
            mm.DoSomeDBStartupStuff();
        }
    }

IMusicManager

实现如下所示:

    private readonly IMusicRepo _musicStoreRepo;
    public MusicManager(IMusicRepo musicStoreRep)
    {
        _musicStoreRepo = musicStoreRepo;
    }

    public void DoSomeDBStartupStuff()
    {
        _musicStoreRepo.InsertSampleStuff();
        _musicStoreRepo.CheckThisAndCheckThat();
    }

IMusicRepo

实现如下所示:

    private readonly MMContext _context;
    public MusicRepo(MMContext context)
    {
        _context = context;
    }

    public void InsertSampleStuff()
    {
        _context.Music.AddAsync(new music("abc"));
        _context.Music.AddAsync(new music("123"));
        _context.SaveChangesAsync();
    }

MMContext

这是这样实现的:

public class MMContext : DbContext
{
    public MMContext(DbContextOptions<MMContext> options) : base(options) {}
    ... OnModelCreating etc...
}

启动时出现异常:

Application startup exception: System.InvalidOperationException: Reset() called on connector with state Executing at Npgsql.NpgsqlConnector.Reset() at Npgsql.ConnectorPool.Release(NpgsqlConnector connector) at Npgsql.NpgsqlConnection.Close(Boolean wasBroken) at Npgsql.NpgsqlConnection.Dispose(Boolean disposing) at System.ComponentModel.Component.Dispose() at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Dispose() at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose() at Microsoft.EntityFrameworkCore.DbContext.Dispose() at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose() at MM.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in \Startup.cs:line 122 --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app) at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.b__0(IApplicationBuilder app) at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.b__0(IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

我不确定是什么导致了这个问题。可能是我使用依赖注入的方式以及我使用范围的方式?帮助表示赞赏。

注意到 void 函数中没有等待异步调用。

public void InsertSampleStuff()
{
    _context.Music.AddAsync(new music("abc"));
    _context.Music.AddAsync(new music("123"));
    _context.SaveChangesAsync();
}

当您尝试保存这些更改时,这可能会导致 DbContext 出现线程问题。

要么使函数异步并正确等待这些调用,要么使用同步函数 API

public void InsertSampleStuff() {
    _context.Music.Add(new music("abc"));
    _context.Music.Add(new music("123"));
    _context.SaveChanges();
}

如果走异步路线,则考虑将该设置代码移到托管服务中并在那里适当地等待它

参考参考Background tasks with hosted services in ASP.NET Core