IdentityDbContext.SaveChanges在Claims.Remove或Claims.Clear之后失败
本文关键字:Claims Clear 之后 失败 Remove SaveChanges IdentityDbContext | 更新日期: 2023-09-27 18:21:41
我直接使用AspNetUserClaims表,因为它主要属于我的ASP.NET应用程序,但也从Windows应用程序中使用。ASP.NET应用程序使用Google进行外部登录,而Windows应用程序定期轮询Google帐户并不时刷新访问令牌。因此,现在我在Windows应用程序下工作。
在尝试从AspNetUserClaims表中删除声明时,我遇到了一个异常。它一直告诉我"UserId字段是必需的。"
如果我禁用dc验证。Configuration.ValidateOnSaveEnabled=false,我看到它试图执行UPDATE查询(将所有值传递为NULL或默认值),而不是DELETE。无论我试图删除哪一个特定的声明,即使我使用Clear方法删除了所有声明,它都会失败。
代码还显示了所有用户当前可用的所有声明(这就是为什么有foreach而不是dc.users.Where),但出于调试目的,我删除了这些部分。
var dc = new IdentityDbContext();
foreach (var u in dc.Users.ToList())
{
if (u.Email == "something@gmail.com")
{
u.Claims.Clear();
}
}
dc.SaveChanges();
这只涉及删除索赔。我成功地使用claims添加了新索赔。通过更改Claim.ClaimValue添加或更新现有索赔的值。原因可能是什么?
事实上,我可以不删除声明,因为我的Windows应用程序只需要更新声明(使用刷新令牌更新访问令牌)。但我很好奇为什么删除不起作用。
好吧,我找到了一种删除令牌的方法,代码是:
var dc = new IdentityDbContext();
var manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(dc));
var user = manager.FindByEmail("something@gmail.com");
Claim c = manager.GetClaims(user.Id).Where(c => c.Type == "GoogleAccessToken").FirstOrDefault();
if (c != null)
{
manager.RemoveClaim(user.Id, c);
}
但仍然不清楚为什么不使用UserManager的原始代码不能删除声明。
这些都是实体框架的怪癖
当你说
user.Claims.Remove(claim);
dbContext.SaveChanges();
这只会将声明对象的外键重置为null,但这是不允许的。EF对此一无所知,因此没有DELETE
语句。
如果您想删除EF中的对象,请执行以下操作:
dbContext.UserClaims.Remove(claim);
但是您需要将IDbSet<UserClaim> UserClaims
映射到dbContext
,因为默认情况下它不可用。
阅读本文