c# - IdentityDbContext.SaveChanges 在 Claims.Remove 或 Claims.Clear 之后失败

标签 c# asp.net-identity-2

我直接使用 AspNetUserClaims 表,因为它主要属于我的 ASP.NET 应用程序,但也由 Windows 应用程序使用。 ASP.NET 应用程序使用 Google 进行外部登录,而 Windows 应用程序会定期轮询 Google 帐户并不时刷新访问 token 。因此,现在我正在该 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 == "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0d7e626068796564636a4d6a606c6461236e6260" rel="noreferrer noopener nofollow">[email protected]</a>")
    {
        u.Claims.Clear();
    }
}
dc.SaveChanges();

这仅涉及删除声明。我成功使用 Claims.Add 添加新声明,或通过更改 Claim.ClaimValue 更新现有声明的值。可能是什么原因?

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

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

var dc = new IdentityDbContext();
var manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(dc));
var user = manager.FindByEmail("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="aad9c5c7cfdec2c3c4cdeacdc7cbc3c684c9c5c7" rel="noreferrer noopener nofollow">[email protected]</a>");
Claim c = manager.GetClaims(user.Id).Where(c => c.Type == "GoogleAccessToken").FirstOrDefault();
if (c != null)
{
    manager.RemoveClaim(user.Id, c);
}

但仍不清楚为什么不使用 UserManager 的原始代码无法删除声明。

最佳答案

这些是 Entity Framework 的怪癖。
当你说

user.Claims.Remove(claim);
dbContext.SaveChanges();

这只会将声明对象的外键重置为空,但这是不允许的。 EF 不知道更多,因此没有 DELETE陈述。

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

dbContext.UserClaims.Remove(claim);

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

this article 中了解有关删除对象的 EF 方法的更多信息

关于c# - IdentityDbContext.SaveChanges 在 Claims.Remove 或 Claims.Clear 之后失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25822538/

相关文章:

c# - 如果提交了错误的凭据,程序将抛出错误

c# - 如何为 EF 中的 POCO 实体添加 C# 自动计算?

c# - 具有父子关系的自引用表使用 LINQ 表示文件树

c# - 如何区分引用是引用数组还是引用单个值?

c# - 验证访问 token - Asp.Net 身份

asp.net-mvc - 如何更改 ASP.Net MVC Identity 2 中的密码验证?

asp.net - 基于 ASP.NET Identity 的两个 ASP.NET 应用程序之间的通用身份验证

c# - Windows\System32\drivers\etc 和 GetDirectories

asp.net-mvc - 在 Identity 2.0 中重定向未经授权的用户

ASP.Net MVC 标识无限重定向循环