![](/img/trans.png)
[英].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.