我正在使用AzureFunctions.Autofac注入我的Azure Functions Web API。配置示例:
public class DIConfig
{
public DIConfig()
{
DependencyInjection.Initialize(builder =>
{
// DAL
builder.Register<IDbContext>(c => new SecretCompanyContext()).InstancePerLifetimeScope();
builder.RegisterType<SecretCompanyContext>().InstancePerLifetimeScope();
builder.RegisterType<SecretCompanyContext>().As<ICartContext>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
// Services
builder.RegisterType<InventoryServices>().As<IInventoryServices>().InstancePerLifetimeScope();
// Controllers ported from ASP.NET MVC Web API
builder.RegisterType<InventoryController>().InstancePerLifetimeScope();
});
}
然后我的Azure函数中,有一类定义了API中的所有方法
[DependencyInjectionConfig(typeof(DIConfig))]
public class InventoryFunctions : FunctionsApi
{
[FunctionName("GetProductsByCategory")]
// /inventory/categories/{id}/products
public static async Task<HttpResponseMessage> GetProductsByCategory(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "inventory/categories/{id}/products")]
HttpRequestMessage req,
TraceWriter log,
int id,
[Inject] InventoryController controller)
{
// do stuff
var result = await controller.GetProductsByCategory(id);
return JsonResponse(result, HttpStatusCode.OK);
}
[FunctionName("GetInventoryBySku")]
// /inventory/skus?sku=ASDF&sku=ASDG&sku=ASDH
public static async Task<HttpResponseMessage> GetInventoryBySku(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "inventory")]
HttpRequestMessage req,
TraceWriter log,
[Inject] InventoryController controller)
{
// do stuff
var result = await controller.QueryInventoryBySkuList(skuList);
return JsonResponse(result, HttpStatusCode.OK);
}
[FunctionName("UpdateProductsQuantity")]
// /inventory
// Post
public static async Task<HttpResponseMessage> UpdateProductsQuantity(
[HttpTrigger(AuthorizationLevel.Function, "put", Route = "inventory")]
HttpRequestMessage req,
TraceWriter log,
[Inject] InventoryController controller)
{
// do stuff
var inventoryProducts = await req.Content.ReadAsAsync<List<InvProductOperation>>();
var result = await controller.UpdateAvailableProductsQuantity(inventoryProducts);
return JsonResponse(result, HttpStatusCode.OK);
}
但是我一直收到此错误:
在此上下文中,第二个操作在上一个操作之前开始 异步操作完成。使用“等待”来确保 调用之前,所有异步操作均已完成 在这种情况下的另一种方法。任何实例成员都不是 保证是线程安全的。
我已验证async
和await
的使用正确,因此遵循错误消息的建议并不能解决问题。似乎是问题所在,IDbContext
没有按预期兑现InstancePerLifetimeScope
。发生这种情况是因为我的InventoryFunctions
类中有多个方法吗?还是AzureFunctions.Autofac不是线程安全的?
答案 0 :(得分:1)
将DbContext的注册更改为此:
builder.Register<IDbContext>(c => new SecretCompanyContext()).InstancePerDependency();
您可以找到关于为什么发生这种情况的更深入的解释here。
答案 1 :(得分:1)
我正在回答这个问题:Autofac - InstancePerHttpRequest vs InstancePerLifetimeScope,它说InstancePerLifetimeScope
与InstancePerRequest
的非ASP.NET等效。
我与开发人员交谈,他们说的事实是,当您仅使用builder.RegisterType<SecretCompanyContext>.As<IDbContext>()
注册时,默认情况下,每个HttpRequest获取一个DbContext是默认行为,所以那里存在一些错误信息。
解决方法是,而不是使用
builder.Register<IDbContext>(c => new SecretCompanyContext()).InstancePerDependency();
或
builder.RegisterType<SecretCompanyContext>().As<IDbContext>().InstancePerLifetimeScope();
一个人应该使用
builder.RegisterType<SecretCompanyContext>().As<IDbContext>();
如果目标是每个HTTP请求一个实例。