UseInMemoryDatabase與UseInternalServiceProvider一起使用。沒有配置數據庫提供商

asp.net-core c# entity-framework entity-framework-core

使用EntityFrameworkCore時,我在註入自定義IAsyncQueryProvider時遇到問題。更確切地說,在使用提供的內存數據庫功能時,我無法注入提供程序。使用默認提供程序(SqlServer),一切正常。

這是我的全球Startup.cs

private void ConfigureEntityFrameworkWithSecurity(IServiceCollection services)
{
    services
        .AddEntityFramework()
        .AddEntityFrameworkSqlServer()
        .AddScoped<IAsyncQueryProvider, CustomEntityProvider>()
        .AddDbContext<APIContext>((sp, options) =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
                .UseInternalServiceProvider(sp);
        });
}

完美無缺 ,我可以在CustomEntityProvider放置一個斷點來驗證它是否確實被注入。目前, CustomEntityProvider非常簡單地實現IAsyncQueryProvider ,並簡單地通過請求。其中沒有包含邏輯。

當我運行測試時,我將webhost配置為使用不同的Startup文件:

public class TestStartup : Startup
{
    public TestStartup(IHostingEnvironment env) : base(env)
    {
    }

    public override void ConfigureServices(IServiceCollection services)
    {
        services
            .AddDbContext<APIContext>((sp, options) =>
            {
                options.UseInMemoryDatabase()
                    .UseInternalServiceProvider(sp);
            });
        base.ConfigureServices(services);
    }
}

使用TestStartup運行測試TestStartup產生錯誤:

System.InvalidOperationException:尚未為此DbContext配置任何數據庫提供程序。可以通過覆蓋DbContext.OnConfiguring方法或在應用程序服務提供程序上使用AddDbContext來配置提供程序。如果使用AddDbContext,那麼還要確保您的DbContext類型在其構造函數中接受DbContextOptions對象,並將其傳遞給DbContext的基礎構造函數。

並正確定義了APIContext

public class APIContext : DbContext
{
    public APIContext(DbContextOptions<APIContext> options)
        : base(options)
    {
    }
    ...
}

TestStartup刪除UseInternalServiceProvider TestStartup工作 - 但是,我不希望我的測試命中實際的數據庫。此外,我希望UseInMemoryDatabase能夠自動將依賴項注入服務提供者 - 因為它本身可以很好地工作。

該錯誤令人困惑,因為內存數據庫我想要使​​用的提供程序。

一般承認的答案

不幸的是,解決方案很簡單。但是,似乎很少有關於將依賴注入與內存數據庫功能一起使用的文檔。它似乎是一個或另一個。希望這個問題能夠為將來不幸遇到這種情況的人們提供幫助。

我下載了EntityFramework源進行調查,發現調用UseInMemoryDatabase創建了一個擴展名InMemoryOptionsExtension ,它本身將添加到服務提供者,即:

public virtual void ApplyServices(IServiceCollection services)
{
    Check.NotNull(services, nameof(services));

    services.AddEntityFrameworkInMemoryDatabase();
}

解決方案就像它看起來一樣簡單:

public class TestStartup : Startup
{
    public TestStartup(IHostingEnvironment env) : base(env)
    {
    }

    public override void ConfigureServices(IServiceCollection services)
    {
        services
            .AddEntityFrameworkInMemoryDatabase()
            .AddDbContext<APIContext>((sp, options) =>
            {
                options.UseInMemoryDatabase().UseInternalServiceProvider(sp);
            });
        base.ConfigureServices(services);
    }
}


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因