[英].Net Core 1 Identity UserManager cached user list not updating
[英]UserManager not updating custom Identity User properly
我正在使用ASP.NET身份+ OpenIddict在EF Core上進行身份驗證。
我擴展了IdentityUser
類,使其包括兩個列表。 StudyTags
和ExpertTags
以及其他一些屬性:
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
StudyTags = new List<Tag>();
ExpertTags = new List<Tag>();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string Location { get; set; }
public List<Tag> StudyTags { get; set; }
public List<Tag> ExpertTags { get; set; }
}
這一切都很好,但是,當我想更新這些列表並保存它們時,更新似乎只在一定范圍內持續存在。 例如,如果我兩次調用下面的API調用,則第一次將標記添加到正確的列表中,而第二次記錄一條消息,表明它已被添加。 我可以檢查用戶並驗證標簽是否如預期的那樣在列表中。
[Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]
[HttpPost("add/tag/{tagType}/{tagName}")]
public async Task<IActionResult> AddTagToUser(int tagType, string tagName)
{
var user = await _userManager.GetUserAsync(User) as ApplicationUser;
if(user == null)
{
_logger.LogError("User not found");
return BadRequest();
}
TagType type = (TagType)tagType;
var tag = _tagService.GetTagByName(tagName);
if(tag == null)
{
_logger.LogError("No tag corresponding to tagName '{0}'", tagName);
return BadRequest();
}
if(type == TagType.Study)
{
if(user.StudyTags.Contains(tag))
{
_logger.LogInformation("{0} already assigned to {1}", tag.ToString(), user.ToString());
}
else
{
_logger.LogInformation("{0} added to {1}", tag.ToString(), user.ToString());
user.StudyTags.Add(tag);
}
}
else if(type == TagType.Expert)
{
if(user.ExpertTags.Contains(tag))
{
_logger.LogInformation("{0} already assigned to {1}", tag.ToString(), user.ToString());
}
else
{
_logger.LogInformation("{0} added to {1}", tag.ToString(), user.ToString());
user.ExpertTags.Add(tag);
}
}
else
{
_logger.LogError("No tagType corresponding to {0}", tagType);
return BadRequest();
}
var result = await _userManager.UpdateAsync(user);
if(result.Succeeded)
{
return Ok(result);
}
else
{
_logger.LogError("Updating Tag failed");
return BadRequest();
}
}
但是,如果我只是嘗試Get
同一用戶的Get
,則StudyTags和ExpertTags列表為空。
[Authorize(ActiveAuthenticationSchemes = OAuthValidationDefaults.AuthenticationScheme)]
[HttpGet]
public async Task<IActionResult> Get()
{
var user = await _userManager.GetUserAsync(User);
if(user == null)
{
_logger.LogError("User not found");
return BadRequest();
}
return Ok(user);
}
我做錯了什么嗎? 任何幫助,將不勝感激!
您的屬性應標記為虛擬。 如果記錄存在於數據庫中,但是在運行GET方法並為用戶獲取數據時未獲取記錄,則是由於延遲加載。 當您訪問用戶對象時,虛擬關鍵字將允許它們被填充。
這就是你想要的:
public virtual List<Tag> StudyTags { get; set; }
public virtual List<Tag> ExpertTags { get; set; }
更新:
因此,看起來需要一個M:M關系。 由於EF Core不支持聯結類的自動創建,因此必須顯式進行。 因此,最后,您的模型必須如下所示:
public class ApplicationUser : IdentityUser
{
//Other Properties
public ICollection<Tag> StudyTags { get; set; }
public ICollection<Tag> ExpertTags { get; set; }
}
public class Tag
{
//Other Properties
public ICollection<ApplicationUser> Users { get; set; }
}
public class UserTags
{
public int UserId { get; set; }
public ApplicationUser User { get; set; }
public int TagId { get; set; }
public Tag Tag { get; set; }
}
並且您的上下文需要更新為包括:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserTag>()
.HasKey(x => new { x.User, x.TagId });
modelBuilder.Entity<UserTag>()
.HasOne(x => x.User)
.WithMany(y => y.UserTags)
.HasForeignKey(x => x.UserId);
modelBuilder.Entity<UserTag>()
.HasOne(x => x.Tag)
.WithMany(y => y.UserTags)
.HasForeignKey(x => x.TagId);
}
在_userManager.GetUserAsync
方法中,您必須編寫代碼以像下面這樣急切地加載StudyTag:
context.User.Include(x => x.StudyTags).Include(x => x.ExpertTags);
如果您的屬性是虛擬的,則僅在您訪問該屬性時才將其加載(延遲加載)。 如果您的屬性不是虛擬的,則應在加載包含該屬性的對象時加載它。
如果要全局關閉延遲加載,可以將其包含在上下文構造函數中:
this.Configuration.LazyLoadingEnabled = false; // careful though keep reading
上面的開關具有全局作用,因此,如果不小心,可能會導致性能問題,因為即使您可能不需要,整個對象圖也會每次加載。
要關閉單個屬性的延遲加載,請將其設置為NON虛擬。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.