为什么我的 EF Core DbContext 不受 DI 绑定?

pha*_*raa 5 c# azure entity-framework-core asp.net-core azure-function-app

我有一个 Azure Function App,其函数在 blob 触发器上运行。我已经证明这个函数可以通过 Azure 门户运行并响应这个 blob 触发器而不会出现问题......或者至少是这样。

现在我已经添加了使用 EF Core (2.2.4) 的功能,在本地调试和发布到 Azure 时都会出现以下错误:

Microsoft.Azure.WebJobs.Host:索引方法“ParseThings”出错。Microsoft.Azure.WebJobs.Host:无法将参数“context”绑定到 AvastusContext 类型。确保绑定支持参数类型。如果您使用绑定扩展(例如 Azure 存储、ServiceBus、计时器等),请确保您已在启动代码中调用扩展的注册方法(例如 builder.AddAzureStorage()、builder.AddServiceBus( )、builder.AddTimers() 等)。

Startup按照 Azure Function App 文档的指示开设了一个课程并且严格按照他们的示例进行操作,除了以下行代替其配置的示例服务之外:

[assembly: FunctionsStartup(typeof(AvstFunctionApp.Startup))]

namespace AvstFunctionApp
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddDbContext<AvastusContext>(options => options.UseSqlServer(Environment.GetEnvironmentVariable("AvastusDb")));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的函数的开头:

public static class ParseThings
{
    [FunctionName("ParseThings")]
    public static void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log, AvastusContext context)
Run Code Online (Sandbox Code Playgroud)

我可以确认该AddDbContext行在调试器中击中,因此可能在幕后发生了一些错误,或者我正在做一些非常愚蠢的事情。

我尝试过但不起作用的事情包括:

  • 添加.BuildServiceProvider(true)AddDbContext行中
  • 使用WebJobsStartup而不是最近广告的FunctionsStartup
  • 降级到.NET Core 2.2.0
  • 将 Function 类和Run方法从静态更改为实例
  • 修复注入的不正确的命名空间AvastusContext

还值得注意的是,此 Function App 项目中还有其他两个函数,它们似乎没有任何严重问题,并且我已经能够使用与 EF Core 类似的方法来实现另一个函数(ASP.NET此解决方案中的 Core MVC)项目。

预先感谢您提供的任何帮助!

PS 我觉得非常奇怪的是,互联网上没有任何关于 .NET Core、Azure Function Apps 和 EF Core 更高版本的描述这种情况的信息,这让我相信这可能是一个简单的错误。但愿不会。

小智 0

也许一种解决方案是您可以尝试在函数中注入 IServiceProvider 而不是 AvastusContext,就像我在下面的存储库类中注入的那样:

private readonly IServiceProvider serviceProvider;

        public SomeRepository(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }
    
        using var context = this.serviceProvider.GetService<XYZDBContext>(); 
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个上下文对象。另外,不知道为什么您要尝试直接访问函数中的上下文,以实现定义上下文类的良好实践,并维护存储库以在代码中执行任何 CRUD 操作。

Startup.cs 您可以添加额外的配置,例如:

builder.Services.AddDbContext<XYZDBContext>(
            options =>
            {
                options.UseSqlServer(
                    conn,
                    sqlServerOptionsAction:
                    sqlOptions =>
                    {
                        sqlOptions.EnableRetryOnFailure(maxRetryCount: 3, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                    });
            }, ServiceLifetime.Transient);
Run Code Online (Sandbox Code Playgroud)

这个配置在我当前的解决方案中工作得很好。试试这个。