EF6 SqlException:违反 PRIMARY KEY 约束...重复键值为 (0)

EF6 SqlException: Violation of PRIMARY KEY constraint ... The duplicate key value is (0)

我知道 SQL,但我对 ORM 很陌生,在 VS 2017 中使用 EntityFramework 6.2.0 在沙盒中玩游戏。 我认为该框架应该使我能够或多或少地像使用 POCO 对象一样进行编码,而不必处理 primary/foreign 键。 一旦我调用下面的代码 context.SaveChanges(); ,更改就会保存在数据库中; 我(还)不了解 EF6 及其文档的哪些内容?

我创建了两个表 Person 和 WorkingHours,它们相互依赖,具有外键和 1:n 关系。

  CREATE TABLE [dbo].[Person](
    [FirstName] [nvarchar](100) NOT NULL,
    [LastName] [nvarchar](100) NOT NULL,
    [BirthDate] [date] NULL,
    [Id] [int] IDENTITY(1,1) NOT NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[WorkingHours](
  [Id] [int] NOT NULL,
  [PersonId] [int] NOT NULL,
  [Date] [date] NOT NULL,
  [Start] [time](7) NOT NULL,
  [Hours] [real] NOT NULL,
 CONSTRAINT [PK_WorkingHours] PRIMARY KEY CLUSTERED 
(
  [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

我从数据库创建了模型。

我尝试创建两个 Person 条目,每个条目都有一个 WorkingHours 条目,并立即将其保存到数据库中。 这是代码:

     static void Main(string[] args)
    {
        using(var context = new EntityFrameworkTrialEntities2())
        {
             // Inserting entries
            var person1 = new Person() { FirstName = "Al", LastName = "Curie", BirthDate = new DateTime(1867, 11, 7) };
            var person2 = new Person() { FirstName = "Al", LastName = "Capone", BirthDate = new DateTime(1899, 1, 7) };
            context.Person.Add(person1);
            context.Person.Add(person2);

            var workingHour1 = new WorkingHour() { Date = new DateTime(1887, 8, 18), Start = new TimeSpan(6, 35, 33), Hours = 4.3F };
            var workingHour2 = new WorkingHour() { Date = new DateTime(1919, 9, 19), Start = new TimeSpan(10, 23, 56), Hours = 3.2F };
            person2.WorkingHours.Add(workingHour1); 
            person1.WorkingHours.Add(workingHour2); 

            context.WorkingHours.Add(workingHour1);
            context.WorkingHours.Add(workingHour2);
            context.SaveChanges(); // <-- place of exeception !!!!!!!!!!!!!!!!!!!!

            // (next step as EF6 trial: here the previously intentionally mixed relationships between person1/2 and workingHour2/1 shall be corrected)

但是在调用 context.SaveChanges() 时;我得到这个例外:

SqlException:违反 PRIMARY KEY 约束 'PK_WorkingHours'。无法在对象 'dbo.WorkingHours' 中插入重复键。 重复键值为 (0)。 声明已终止。**

我尝试了更多 context.SaveChanges() 和 Attach() 以及其他命令的不同方式,但我总是失败并出现上述异常。 context.Configuration.ProxyCreationEnabled 默认设置为 true。

这里是模型类:

public partial class Person
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Person()
    {
        this.WorkingHours = new HashSet<WorkingHour>();
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Nullable<System.DateTime> BirthDate { get; set; }
    public int Id { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<WorkingHour> WorkingHours { get; set; }
}


public partial class WorkingHour
{
    public int Id { get; set; }
    public int PersonId { get; set; }
    public System.DateTime Date { get; set; }
    public System.TimeSpan Start { get; set; }
    public float Hours { get; set; }

    public virtual Person Person { get; set; }
}

第一个问题是 WorkingHourPrimary Key 不是 Identity Key 这就是为什么它总是被设置为 0(默认每个 WorkingHourint) 的值,因此它被复制了。

所以 IdWorkingHour [Id] [int] IDENTITY(1,1) NOT NULL

第二个问题在以下几行中:

person2.WorkingHours.Add(workingHour1); // adding with person
person1.WorkingHours.Add(workingHour2); // adding with person

context.WorkingHours.Add(workingHour1); // adding individually
context.WorkingHours.Add(workingHour2); // adding individually

此处您在上下文中添加了两次 WorkingHour。一个具有 Person 个实体,另一个是单独的。所以删除第二组,只使用第一组如下:

person2.WorkingHours.Add(workingHour1); 
person1.WorkingHours.Add(workingHour2);

我认为你的问题是因为 [Id] in [WorkingHours]:

  CREATE TABLE [dbo].[WorkingHours](
      [Id] [int] NOT NULL,
      [PersonId] [int] NOT NULL,
      [Date] [date] NOT NULL,
      [Start] [time](7) NOT NULL,
      [Hours] [real] NOT NULL,
     CONSTRAINT [PK_WorkingHours] PRIMARY KEY CLUSTERED 
    (
      [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]

按如下方式更改并重试。

 CREATE TABLE [dbo].[WorkingHours](
      [Id] [int] IDENTITY(1,1) NOT NULL,
      [PersonId] [int] NOT NULL,
      [Date] [date] NOT NULL,
      [Start] [time](7) NOT NULL,
      [Hours] [real] NOT NULL,
     CONSTRAINT [PK_WorkingHours] PRIMARY KEY CLUSTERED 
    (
      [Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]