【问题标题】:Violation of PRIMARY KEY constraint in Entity Framework code first link table违反实体框架代码第一个链接表中的 PRIMARY KEY 约束
【发布时间】:2013-07-04 17:05:19
【问题描述】:

我有一个用户表和一个角色表。有一个自动生成的 UsersRoles 链接表,其中包含来自 User 和 Roles 表的 Id。这是使用以下代码生成的:

modelBuilder.Entity<User>()
                .HasMany(u => u.Roles)
                .WithMany(r => r.Users)
                .Map(c => { 
                    c.MapLeftKey("UserId");
                    c.MapRightKey("RoleId");
                    c.ToTable("UsersRoles");
                });

当我尝试添加不相关的实体并调用 Context.SaveChanges() 时,我收到以下错误:

违反主键约束“PK_UsersRoles”。无法插入 对象“dbo.UsersRoles”中的重复键。重复键值为 (2beaf837-9034-4376-9510-b1609c54efbe, dcd16d00-d46e-4d48-8328-3e7b35b11ccf)。该声明已 终止。

我已经检查了Conext.ChangeTracker.Entries() 错误中提到的项目,并且实体状态被标记为未更改。

唯一标记为已添加的实体是我尝试添加的新记录,其他所有内容都标记为未更改。

添加实体的代码:

 RoleGroup group = Context.RoleGroups.Create();
 group.Title = roleGroupName;
 Context.Set<RoleGroup>().Add(group);
 Context.SaveChanges();

有人知道为什么会这样吗?

【问题讨论】:

  • 您应该发布将实体添加到上下文的代码
  • 您能准确地显示您检查过的内容吗?我怀疑您只验证了 RoleUser 实体没有改变。
  • 感谢您的提问,我已更新我的问题以添加更多信息。希望这会有所帮助。
  • 你的意思是Context.Set&lt;RoleGroup&gt;().Add(group);
  • 我还是不明白。添加 RoleGroup 如何导致不相关的 UserRoles 表中的主键冲突?

标签: c# .net entity-framework ef-code-first


【解决方案1】:

为了补充 Slauma 的答案,看起来如果您在这些自动多对多事物之一上设置 ICollection 属性,EF 会感到困惑并且没有意识到您正在通过这样做清除集合元素。

所以不要这样做:

user.Roles = new List<Role>();
user.Roles.Add(role);

你必须这样做:

user.Roles.Clear();
user.Roles.Add(role);

这对我有用。

不过,您不应该这样做。这应该是 EF 中的一个错误。

【讨论】:

  • 刚刚遇到了同样的问题。绝对应该被视为一个错误。
  • 这里有同样的问题。就我而言,我在每个层次结构的表配置中的子对象上有一个导航属性。为了让它正常工作,我必须通过 DbContext.Entry(entity).Collection(x => x.Children).Load() 手动加载实体的子代。仅通过查询加载它们是不够的。然后要更新列表,我必须清除并添加新条目。
【解决方案2】:

UserUserId = 2beaf837-9034-4376-9510-b1609c54efbeRoleRoleId = dcd16d00-d46e-4d48-8328-3e7b35b11ccf 处于状态 Unchanged 的事实并不意味着没有任何内容写入数据库。

特别是对于多对多关系(通常用于独立关联),EF 为 relationship 本身维护一个与 entity 状态不同的状态。如果一个条目被插入到链接表中,则意味着这两个实体的关系条目处于状态Added,尽管这些实体的实体状态是Unchanged。枚举DbContexts ChangeTracker 时看不到关系条目。它只会返回实体状态。您必须下到底层ObjectContext 才能查询关系状态。

例子:

using (var ctx = new MyContext())
{
    var user = ctx.Users.Find(1);
    var role = ctx.Roles.Find(5);

    user.Roles = new List<Role>();
    user.Roles.Add(role);

    ctx.SaveChanges();
}

这里userrole 都将处于Unchanged 状态,但仍将一条记录插入到链接表中。如果用户 1 和角色 5 已在数据库中链接,则此代码将引发异常。

添加group 与问题无关。只有对 SaveChanges 的调用会导致异常,因为您很可能在问题中的代码 sn-p 之前的某处创建了两个实体之间的关系。

【讨论】:

    【解决方案3】:

    您正在尝试将相同的用户/角色组合插入到 UserRoles 表中:

    Violation of PRIMARY KEY constraint 'PK_UsersRoles'. Cannot insert duplicate key in object 'dbo.UsersRoles'. The duplicate key value is (2beaf837-9034-4376-9510-b1609c54efbe, dcd16d00-d46e-4d48-8328-3e7b35b11ccf). The statement has been terminated.

    查看哪个用户的 ID 为 2beaf837-9034-4376-9510-b1609c54efbe,哪个角色的 ID 为 dcd16d00-d46e-4d48-8328-3e7b35b11ccf。 如果您确定您只输入了该用户一次,那么插入数据的方法是否会在您不知情的情况下被多次调用?

    【讨论】:

      【解决方案4】:

      希望有人会觉得它有帮助我发现在 EF 中更改现有列表与创建新列表之间存在很大差异。

      在这种情况下,我正在进行更新,并认为建立一个我想要的项目的新列表是最简单的。但是,如果某些项目已经添加到列表中,我会在保存时遇到主键冲突。

      我最终保留了相同的列表,只是对其进行了修改。清除它并读取就可以了,创建一个新列表就不行了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多