【问题标题】:IdentityDbContext.SaveChanges fails after Claims.Remove or Claims.Clear在 Claims.Remove 或 Claims.Clear 之后 IdentityDbContext.SaveChanges 失败
【发布时间】:2014-09-13 11:01:24
【问题描述】:

我直接使用 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.Add 成功添加了新的声明。通过更改 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 的原始代码无法删除声明。

【问题讨论】:

    标签: c# asp.net-identity-2


    【解决方案1】:

    这些是实体框架的怪癖。
    当你说

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

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

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

    dbContext.UserClaims.Remove(claim);
    

    但是您需要将IDbSet&lt;UserClaim&gt; UserClaims 映射到您的dbContext,因为默认情况下它不可用。

    this article中阅读更多关于 EF 删除对象的方法

    【讨论】:

      猜你喜欢
      • 2020-06-07
      • 1970-01-01
      • 2015-11-13
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 2014-10-29
      相关资源
      最近更新 更多