我正在構建一組API。其中之一是一個認證API,它返回JWT令牌。我正在嘗試實施「每次操作的會話」方法,其中包含ActionFiltersAttribute
。我的控制器裝飾有此屬性:帶有任務/線程的RESTful API中的NHibernate會話管理
public class NHibernateSessionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var session = NHibernateSessionManager.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var session = CurrentSessionContext.Unbind(NHibernateSessionManager.SessionFactory)
if (session != null)
{
if (session.Transaction.IsActive)
{
try
{
session.Transaction.Commit();
}
catch
{
session.Transaction.Rollback();
}
}
session.Close();
}
}
}
問題在哪裏?使用NHibernate來管理用戶而不是實體框架我已經實現了所有需要的ASP.NET Identity接口,並且它們都返回Task<T>
。例如以下動作:
AccountController.cs
public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
model.NewPassword);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
有ChangePasswordAsync
內部調用多種方法至極裏面有新的任務,其中SessionFactory.GetCurrentSession()
導致NullException
代碼。據我所知,因爲那是另一個線程和上下文。 在代碼中,第一次保存嘗試沒有失敗,第二次沒有失敗。重複的代碼僅用於說明情況。
UserStore.cs
public System.Threading.Tasks.Task UpdateAsync(UserModel user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
//Here the Session is found
DataProviderI<UserModel, int> prov = new DataProviderImplGeneric<UserModel, int>();
prov.Save(user);
return Task.Factory.StartNew(() =>
{
//Here the Session is NOT found
DataProviderI<UserModel, int> prov2 = new DataProviderImplGeneric<UserModel, int>();
prov.Save(user);
});
}
什麼對付這一點,所有的Action
時得到同樣ISession
的最佳方式?
據我所知,NHibernate不支持異步調用,我可以在返回類型爲Task.FromResult(0)
的虛方案或Task.FromResult<T>(T)
上重構方法,其中T是一個對象,但我想知道是否有另一種解決方案利用並行性
看看使用DI庫,[simpleinjector](https://simpleinjector.org/index.html)是一樣的好。使用DI容器,您可以將實例的生命週期與作用域綁定在一起,在這種情況下,您希望將「ISession」綁定到Web請求。 SimpleInjector非常適合這一點,並且適用於任務和異步。 –