爲了簡化這個問題,我將描述更高級別的問題,然後根據需要進入任何實現細節。用戶管理器在.Net標識中的奇怪行爲
我在開發中使用我的應用程序中的ASP.NET身份。在一系列請求的特定場景中,UserManager首先獲取當前用戶(至少一個FindById請求),用戶被抓取到。在後續的請求中,我更新了由UserManager.Update保存的此用戶的信息,我可以看到數據庫中保留的更改。
問題在於,在進一步的後續請求中,從FindById獲取的用戶對象不會更新。這很奇怪,但可能是關於在UserManager中緩存的內容我不明白。但是,當我跟蹤數據庫調用時,我發現UserManager確實正在向數據庫發送sql-requests以獲取用戶。
這就是它真正奇怪的地方 - 即使數據庫被確認爲最新的,UserManager仍然以某種方式從這個過程中返回一箇舊對象。當我自己運行直接跟蹤到數據庫的完全相同的查詢時,我按預期得到更新的數據。
這是什麼黑魔法?
很明顯,某些東西被緩存在某處,但爲什麼它會對數據庫進行查詢,只是爲了忽略它所獲取的更新數據?
例
此示例下面更新一切按預期在db爲每個請求到控制器的動作,和時GetUserDummyTestClass呼籲findById上的UserManager的另一實例我可以跟蹤SQL請求,並能直接測試這些數據庫並驗證它們是否返回更新的數據。但是,從同一行代碼中返回的用戶對象仍然具有舊值(在這種情況下,應用程序啓動後的第一次編輯,無論調用Test操作多少次)。
控制器
public ActionResult Test()
{
var userId = User.Identity.GetUserId();
var user = UserManager.FindById(userId);
user.RealName = "name - " + DateTime.Now.ToString("mm:ss:fff");
UserManager.Update(user);
return View((object)userId);
}
Test.cshtml
@model string
@{
var user = GetUserDummyTestClass.GetUser(Model);
}
@user.RealName;
GetUserDummyTestClass
public class GetUserDummyTestClass
{
private static UserManager<ApplicationUser> _userManager;
private static UserManager<ApplicationUser> UserManager
{
get { return _userManager ?? (_userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()))); }
}
public static ApplicationUser GetUser(string id)
{
var user = UserManager.FindById(id);
return user;
}
}
更新
正如Erik指出的,我不應該使用靜態UserManagers。但是,如果我保持UserManager在GetUserDummyTest中綁定到HttpContext(每個HttpRequest持久化它),以防在請求期間多次使用它,它仍然緩存它通過Id獲取的第一個User對象,並忽略任何更新從另一個用戶管理器。因此表明真正的問題確實是我使用兩種不同的UserManagers作爲trailmax建議的,並且它不是爲這種用法而設計的。
在我上面的示例中,如果我將UserManager保留在GetUserDummyTestClass持久性HttpRequest上,請添加Update-method並僅在控制器中使用它,一切正常。
因此,如果要得出結論,說明如果我想使用控制器範圍之外的UserManager中的邏輯,我必須將UserManager實例全局化爲可綁定的適當類HttpContext的實例,如果我想避免創建和處置一次性使用的實例?
更新2
調查遠一點,我意識到,我確實打算每個請求使用一個實例,這實際上已經被設置爲OwinContext在Startup.Auth後來像訪問這樣的:
using Microsoft.AspNet.Identity.Owin;
// Controller
HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>()
// Other scopes
HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>()
這實際上是令人尷尬的明顯看提供的默認的AccountController的設置,但我想以上證明:相當分散描述的相當奇怪和意外的行爲。不過,理解這種行爲的原因是很有趣的,儘管使用OwinContext.GetUserManager不會再成爲問題了。
我知道一個人應該在發佈了一個新問題後,我會在一段時間後掛斷,但不幸的是,我的時區迫使我暫時離開。如果有人有問題,請耐心等待。 – Alex 2014-09-06 16:25:31
你可以發佈一個示例代碼來重現你的問題嗎? – trailmax 2014-09-07 16:54:02
@trailmax更新 – Alex 2014-09-08 16:15:08