【问题标题】:Entity Framework Code First - Cannot insert duplicate key in object 'db'实体框架代码优先 - 无法在对象“db”中插入重复键
【发布时间】:2011-03-27 14:08:02
【问题描述】:

我首先在我的一个项目中使用新的 EF 代码,但我遇到了一个奇怪的错误,我的模式是:

abstract class Member
{
   public virtual int MemberId;
  ... some other stuff

}

class User : Member
{
    public virtual string Name;
    ... some more props no new key defined
}

class MyDbContext
{
    public DbSet<User> Users {get;set;}
}

部署到 SQL Server 的结果还不错,我有一个成员表和一个用户表 (TPC)。 现在我主要有以下代码:

static Main()
{
   User x,y;
   using(MyDbContext ctx = new MyDbContext())
   {


    x = ctx.Users.Create();
    y = ctx.Users.Create();
    x.Name = "SomeUser";
    y.Name = "SomeUser2";
    ctx.SaveChanges();

   }
}

在保存更改时我得到:

“未处理的异常: System.Data.Entity.Infrastructure.DbUpdateException: 更新时出错 条目。请参阅内部异常 细节。 ---> System.Data.UpdateException:一个错误 更新条目时发生。 有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient .SqlException:违反PRIMARY 键约束 'PK_用户_0CF04B1821B6055D'。不能 在对象中插入重复键 'dbo.Users'。”

MemberId 默认情况下是身份,所以我只是看不到这里发生了什么。我尝试使用 new 创建实例并将它们附加到上下文但错误是相同的,有什么想法吗? 数据库为空!

谢谢。

编辑:忘了告诉 Member 是一个抽象类,抱歉。

【问题讨论】:

    标签: c# entity-framework ef-code-first entity-framework-4.1


    【解决方案1】:

    我刚刚对其进行了测试,TPC 中的派生类型表(每个具体类型的表) 继承没有将 PK 定义为 EF 4.1 RC 中的标识。

    【讨论】:

    • 没错,但是 Member 表有一个身份 PK,所以它应该自动进行绑定
    • 不应该,因为它是每个具体类型的表格。每个表处理自己的 PK。此外,身份列不应在 TPC 继承中使用,因为如果您查询所有成员,它也会返回用户。如果您不更改身份的种子,您将很容易获得具有相同 ID 的用户和成员。在这种情况下,我预计会有例外。
    • 这是有道理的,问题是我有一些公共信息(成员)和一些其他特定信息(例如用户、管理员、访客)我已经将成员映射到一个表,因为如果我想要要知道一些成员名称,我不需要知道它是用户还是管理员等。关键是用户直接是成员,所以不可能有相同的 id ...成员也是一个抽象类,所以我甚至无法创建实例。 . .
    • 你真的需要继承吗?或者更好的是你真的需要TPC继承吗? TPH 还不够吗(单个表和鉴别器列中的所有成员都不同类型的成员)?
    • 没有 TPC 是最好的,因为 90% 的时间我不需要加载用户信息,这就是原因
    【解决方案2】:
    1. MemberId 是否自动递增?
    2. 您是否检查过您创建的用户的 ID(以 console.Writeline 为例)?
    3. 如果您执行以下操作,它是否有效:

      x = ctx.Users.Create();        
      x.Name = "SomeUser";        
      ctx.SaveChanges();        
      y = ctx.Users.Create();        
      y.Name = "SomeUser2";        
      ctx.SaveChanges();
      

    您应该在修改之前尝试附加您的实体。

    【讨论】:

    • 不,它不起作用,属性 MemberId 是身份,所以它不应该在插入查询中。 . . id 总是 0 这就是问题所在,但是当我提交更改时,EF 应该自动更改代理 MemberId
    • 您应该在修改实体之前尝试附加它。
    • 它给出了具有相同问题的其他异常,“具有相同键的对象已经存在”...
    • 如果在保存之前将 entityKey 设置为 null 会发生什么?
    【解决方案3】:

    我刚遇到这个。与标记的答案状态一样,TPC 不会将密钥设置为身份。所以你可以为它使用注解:

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    

    【讨论】:

      【解决方案4】:
      • 我也遇到了重复键的问题。对我来说原因是我误用了

        Id = new Guid()

      而不是

      Id = Guid.NewGuid()
      

      在初始化我的数据库的工厂方法中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-24
        • 1970-01-01
        • 2019-01-14
        相关资源
        最近更新 更多