我有一个棘手的要求,我需要创建通过 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/