首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IdentityDbContext.SaveChanges在Claims.Remove或Claims.Clear之后失败

IdentityDbContext.SaveChanges在Claims.Remove或Claims.Clear之后失败
EN

Stack Overflow用户
提问于 2014-09-13 11:01:24
回答 1查看 1.3K关注 0票数 2

我直接使用AspNetUserClaims表,因为它主要属于我的ASP.NET应用程序,但也是从一个ASP.NET应用程序中使用的。ASP.NET应用程序使用谷歌进行外部登录,而Windows应用程序定期轮询谷歌帐户,并不时刷新访问令牌。因此,现在我在Windows应用程序下工作。

当我试图从AspNetUserClaims表中删除一个声明时,我得到了一个异常。它一直告诉我“UserId字段是必需的”。

如果使用dc.Configuration.ValidateOnSaveEnabled = false禁用验证,则会看到它尝试执行UPDATE查询(将所有值作为NULL或默认值传递),而不是DELETE。它失败了,无论我试图删除哪个特定的声明,即使我用明确的方法将它们全部删除。

该代码还显示了所有用户当前可用的所有声明(这就是为什么要使用foreach而不是dc.Users.Where),但为了调试目的,我删除了这些部分。

代码语言:javascript
复制
var dc = new IdentityDbContext();
foreach (var u in dc.Users.ToList())
{
    if (u.Email == "something@gmail.com")
    {
        u.Claims.Clear();
    }
}
dc.SaveChanges();

这只涉及取消索赔。我成功地用Claims.Add添加了新的声明,或者用更改的Claim.ClaimValue更新了现有声明的值。可能是什么原因?

实际上,我可以不删除声明,因为我的Windows应用程序只需要更新声明(使用刷新令牌更新访问令牌)。但我很好奇为什么删除不起作用。

好吧,我找到了一种用以下代码删除令牌的方法:

代码语言:javascript
复制
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的原始代码无法删除声明。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-15 22:47:42

这些都是实体框架的怪癖。

当你说

代码语言:javascript
复制
user.Claims.Remove(claim);
dbContext.SaveChanges();

这只会将claim的外键重置为null,但这是不允许的。EF不知道更多,因此没有DELETE语句。

如果要删除EF中的对象,请执行以下操作:

代码语言:javascript
复制
dbContext.UserClaims.Remove(claim);

但是您需要将IDbSet<UserClaim> UserClaims映射到您的dbContext,因为它在默认情况下不可用。

阅读更多有关EF-在这篇文章中删除对象的方法

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25822538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档