为什么我的EF Core DbContext不受DI约束?

时间:2019-05-17 01:50:30

标签: c# azure asp.net-core entity-framework-core azure-function-app

我有一个Azure函数应用程序,该函数具有在Blob触发器上运行的功能。我已经证明此功能可以在Azure门户中运行,并且可以响应blob触发器而不会出现问题...或者至少可以做到。

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

  

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

我按照Azure Function App文档here的指示,拥有一个Startup类,除了下面几行代替其配置的示例服务外,还沿用了他们的示例:

[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")));
        }
    }
}

函数的开头:

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

我可以确认AddDbContext正在被调试器击中,因此大概是这里的幕后发生了一些错误,或者我做的事情太愚蠢了。

我尝试过的没用的东西包括:

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

还值得注意的是,此Function App项目中还有两个其他功能似乎没有任何严重的问题,并且我已经能够使用类似的方法将依赖项注入与EF Core一起用于另一个(此解决方案中的ASP.NET Core MVC)项目。

在此先感谢您提供任何帮助!

P.S。我发现非常怪异的是,internet上的.NET Core,Azure Function应用程序和EF Core的更高版本没有任何描述这种情况的东西,这使我相信这可能是一个简单的错误。希望不会。

2 个答案:

答案 0 :(得分:0)

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

private readonly IServiceProvider serviceProvider;

        public SomeRepository(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }
    
        using var context = this.serviceProvider.GetService<XYZDBContext>(); 

这将为您提供一个上下文对象。另外,不确定为什么要尝试直接在函数中访问上下文以作好实践,请定义一个上下文类,并维护存储库以执行代码中的任何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);

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

答案 1 :(得分:0)

函数应用无法解析函数中的 dbcontext,因为它只能解析 BindingContext。您需要创建自定义绑定才能在函数应用中直接使用 dbcontext。

通过 DI 注入 dbcontext 的其他方法是将其传递给构造函数并在函数中使用类级别变量。

public class ParseThings
{
    private AvastusContext _context;
    public ParseThings(AvastusContext context){
        _context = context;
    }

    [FunctionName("ParseThings")]
    public void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log){
      // use _context here
    }
}

如果仍然无法解决,您可能需要查看functionsStartup是否配置正确