c# - 需要在运行时使用 Azure Function 中的 ServiceProvider 创建服务

标签 c# azure azure-functions azure-durable-functions

我有一个棘手的要求,我需要创建通过 Azure 函数中的构造函数 DI 创建的服务的副本

public MyFunction(IMyService myService,
             IServiceProvider serviceProvider, 
             ServiceCollectionContainer serviceCollectionContainer) 
{
    _myService = tmToolsService;
    _serviceProvider = serviceProvider;
    _serviceCollectionContainer = serviceCollectionContainer;
}

[FunctionName("diagnostic-orchestration")]
public async Task DiagnosticOrchestrationAsync(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{

}
    

这个服务有很多依赖项,所以我真的不想走手动 Activator.CreateInstance 路线

我尝试了两种不同的方法

方法 1

我有 ServiceCollectionContainer。这是在启动的配置中填写的,只是保存服务

public override void Configure(IFunctionsHostBuilder builder)
{
   base.Configure(builder);

   var services = builder.Services; 
   services.AddSingleton(s => new ServiceCollectionContainer(services));
}

在我的函数中我调用

var provider = _serviceCollectionContainer.ServiceCollection.BuildServiceProvider();
if (provider.GetService<IMyService>() is IMyService myService)
{
   await myService.MyMathodAsync();
}

这会引发错误

System.InvalidOperationException: 'Unable to resolve service for type 
'Microsoft.Azure.WebJobs.Script.IEnvironment' while attempting to activate
'Microsoft.Azure.WebJobs.Script.Configuration.ScriptJobHostOptionsSetup'.'

我相信这可能是因为虽然服务集合看起来不错(276 个注册服务),但我在网上看到引用资料说配置可能不可靠

方法 2

第二种方法是更传统的方法,我只是尝试使用注入(inject)的服务提供者而不做任何更改

if (_serviceProvider.GetService<IMyService>() is IMyService myService)
{
   await myService.MyMathodAsync();
}

但是如果我使用这种方法,我会收到错误

“范围已处置{no name}已处置,作用域实例已处置且不再可用

我该如何解决这个问题?

我正在处理大日期范围的数据。我需要分割日期范围并使用我的服务来处理每个日期范围。我的服务有存储库。每个存储库都有一个 DbContext。让每个日期段在其自己的服务上下文中运行允许我并行运行处理,而无需并行运行 DbContext 查询,这会导致 Ef Core 出现问题

此处理在持久函数内运行

最佳答案

我不知道这对于 Azure Functions 是否适用,而且我对持久功能没有经验,尽管主要目标似乎是通过 IMyService 通过 ef core 运行并行查询,然后您可以在构造函数中:

public MyFunction(IServiceScopeFactory serviceScopeFactory) 
{
  _serviceScopeFactory = serviceScopeFactory;
}

然后在函数调用中,假设您有一个 IEnumerable“yourSegments”,其中包含要并行处理的内容:

var tasks = yourSegments.Select(async segment =>
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var IMyService = scope.ServiceProvider.GetRequiredService<IMyService>();
                await IMyService.MyMathodAsync(segment);


            }
        });

 await Task.WhenAll(tasks);

我从一篇很好的博客文章中得到了这个,它解释了“Since we project our parameters to multiple tasks, each will have it's own scope which can resolve it's own DbContext instance.

关于c# - 需要在运行时使用 Azure Function 中的 ServiceProvider 创建服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74509986/

相关文章:

c# - 我如何将控制台输出添加到 Windows wpf 应用程序 C#

c# - 如何使用 EF5 包含从一种数据库类型到另一种实体类型的转换?

c# - Azure Function 函数如何使用托管标识获取对 Azure 表存储的引用?

c# - 无法将类型为 'MyType' 的对象转换为类型 'IMyInterface` 1[System.IConvertible]'

c# - 当 Controller 方法具有异步后缀时,AspNetCore 3.0(从 2.2 升级)路由似乎中断

Azure Blob 容器备份和恢复

javascript - 如何在 Azure Function 中使用 Azure 存储表?

c# - Azure Function blob 输入与服务总线触发器绑定(bind)

Azure B2C自定义布局重定向到域提示但不采用login_hint

sql-server - Windows Azure 上的 WCF 服务 - 连接到本地 SQL Server 数据库