C# 在构造函数中异步设置控制器属性
我有一个完全异步的MVC API,它将一个接口注入其所有控制器:C# 在构造函数中异步设置控制器属性,c#,asynchronous,dependency-injection,async-await,C#,Asynchronous,Dependency Injection,Async Await,我有一个完全异步的MVC API,它将一个接口注入其所有控制器: 公共页面控制器(IDataAdapter dataAdapter){ _dataAdapter=dataAdapter; } 接口的实现需要在其SQLConnection对象上设置访问令牌。托管身份安全访问需要此访问令牌(请参阅)。在构造控制器时需要设置该令牌,因此在每次新请求时都需要设置该令牌。令牌可以更改,因此我们不能让它成为静态值。这就是我们今天在接口实现中所做的: 公共部分类DataAdapter:BaseEntityD
公共页面控制器(IDataAdapter dataAdapter){
_dataAdapter=dataAdapter;
}
接口的实现需要在其SQLConnection对象上设置访问令牌。托管身份安全访问需要此访问令牌(请参阅)。在构造控制器时需要设置该令牌,因此在每次新请求时都需要设置该令牌。令牌可以更改,因此我们不能让它成为静态值。这就是我们今天在接口实现中所做的:
公共部分类DataAdapter:BaseEntityDataAdapter,IDataAdapter{
AppInsightsLogger _log=新的AppInsightsLogger();
#区域构造函数
///
///实例化数据适配器并取出dsn信息
///
公共DataAdapter():基(“db”){
试一试{
var conn=base.Database.Connection作为System.Data.SqlClient.SqlConnection;
conn.AccessToken=(新AzureServiceTokenProvider()).GetAccessTokenAsync(“https://database.windows.net/三、结果;
}捕获(例外情况除外){
_LogError(ex);
投掷;
}
}
}
您可以看到,我们使用.Result来计算异步操作,而异步操作实际上是同步运行的。我知道我应该使用工厂模式,如下所示:
public async Task<DataAdapter> ConstructAdapterAsync() {
try {
DataAdapter da = new DataAdapter();
var conn = da.Database.Connection as System.Data.SqlClient.SqlConnection;
conn.AccessToken = await (new AzureServiceTokenProvider()).GetAccessTokenAsync("https://database.windows.net/");
return da;
} catch (Exception ex) {
_log.LogError(ex);
throw;
}
}
公共异步任务ConstructAdapterAsync(){
试一试{
DataAdapter da=新的DataAdapter();
var conn=da.Database.Connection作为System.Data.SqlClient.SqlConnection;
conn.AccessToken=await(新AzureServiceTokenProvider()).GetAccessTokenAsync(“https://database.windows.net/");
返回da;
}捕获(例外情况除外){
_LogError(ex);
投掷;
}
}
但这仍然给我留下了一个问题,在控制器构造函数中,如果不强制异步工厂函数同步运行,我就无法调用它。我是否可以异步设置此属性 当我需要类似的东西时,我使用了工厂模式,但有两个关键点:
private
属性和方法private
,这样没有使用工厂方法的人就不能使用该类当我需要一些类似的东西时,我使用了工厂模式,但有两个关键点:
private
属性和方法private
,这样没有使用工厂方法的人就不能使用该类简单的答案是:不要在构造函数中执行异步操作,而是在其他地方初始化这些操作。也不要使用
.Result
,尤其是在ASP.NET中,因为这样可能会导致阻塞。@DavidG当然,但在这种情况下,是否还有其他解决方法?当一个新的请求进入时(据我所知),框架会自动调用API控制器的构造函数,并且需要在数据库上的任何内容进入之前设置此属性。也许您需要一个创建SQL连接的工厂。控制器构造函数可以将工厂作为依赖项。然后,当您需要一个SQL连接(在您的操作方法中)时,您可以在工厂中调用异步方法,以获得具有访问令牌的正确构造的连接。简单的答案是:不要在构造函数中执行异步操作,请在别处初始化这些操作。也不要使用.Result
,尤其是在ASP.NET中,因为这样可能会导致阻塞。@DavidG当然,但在这种情况下,是否还有其他解决方法?当一个新的请求进入时(据我所知),框架会自动调用API控制器的构造函数,并且需要在数据库上的任何内容进入之前设置此属性。也许您需要一个创建SQL连接的工厂。控制器构造函数可以将工厂作为依赖项。然后,当您需要一个SQL连接(在您的操作方法中)时,您可以在工厂上调用异步方法,以获得一个具有访问令牌的正确构造的连接。