【问题标题】:Entity Framework proxy for an IdentityUser causes PK violation on SaveIdentityUser 的实体框架代理导致保存时违反 PK
【发布时间】:2014-03-03 12:26:27
【问题描述】:

我正在使用 Entity Framework 6,我正在编写一个 Save 方法来更新现有“案例”的详细信息,如下所示:

public void Save(User user, Case @case)
{
    if (@case.Id == 0)
    {
        // deal with new case scenario
    }
    else
    {
        var existing = GetCase(@case.Id);

        // update existing's properties with those in @case

        context.Entity(existing).State = EntityState.Modified;
        context.Entry(existing.SubEntity1).CurrentValues.SetValues(@case.SubEntity1);
        context.Entry(existing.SubEntity2).CurrentValues.SetValues(@case.SubEntity2);
    }

    context.SaveChanges();
}

Case 类型有一个名为 RaisedBy 类型为 User 的属性,该属性派生自 ASP.NET Identity 的 IdentityUser

当调用GetCase 时,我使用IQueryable.Include 同时加载附加到RaisedBy 属性的用户。它似乎将User 作为代理加载,调试时的手表显示类型为System.Data.Entity.DynamicProxies.User_,后跟一个看起来像哈希的非常长的值。

context.SaveChanges() 被调用时,EF 似乎会尝试将用户重新写入表,从而产生带有消息的DbUpdateException

违反主键约束“PK_dbo.IdentityUsers”。无法在对象“dbo.IdentityUsers”中插入重复键。重复键值为 (0799b4c2-a38e-430c-8031-1c27878f2f43)。 声明已终止。

据我所知,RaisedBy 用户与从上下文中加载的用户完全相同,所以我很难看出问题是如何蔓延的。

【问题讨论】:

  • @case 被跟踪了吗?
  • @case 未被跟踪,它是 Case 的实例,其中包含我想要对 existing 进行的更改,已被跟踪。

标签: entity-framework primary-key dbcontext asp.net-identity


【解决方案1】:

鉴于我从问题中省略的代码,在评论后面

// update existing's properties with those in @case

没有人能回答我一点也不奇怪。

问题在于,在那段省略的代码中:

existing.Events.Add(new Event
{
    CaseId = @case.Id,
    Author = user,
    Text = existing.GetChangeDescription(@case),
    DateTime = now,
    EventType = EventType.Update
});

我正在设置与用户对象的关联,实体框架随后会将其状态设置为已添加,这很公平,因为在此阶段没有在上下文中加载此用户的痕迹,即使有,我会得到一个不同的“无法使用相同的键跟踪相同类型的对象”错误。最好的方法是:

  • 使用 DbSet.Find 从数据库加载用户,将传入的用户设置为此加载的用户
  • 不要设置导航属性,将其保留为 null 并改为在 Event 对象上设置 AuthorId
  • 做一些聪明的事情,查询上下文以查看用户是否已经加载,如果没有,则使用 State = EntityState.Unchanged 将传递的用户附加到上下文(类似于第一个选项,只是避免数据库命中)

我选择了选项 1,因为它最适合我当前的架构,但我正在考虑进行重构以使选项 3 成为可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    相关资源
    最近更新 更多