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; }
}
第一个问题是 WorkingHour
的 Primary Key 不是 Identity Key
这就是为什么它总是被设置为 0
(默认每个 WorkingHour
的 int
) 的值,因此它被复制了。
所以 Id
列 WorkingHour
[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]
我知道 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; }
}
第一个问题是 WorkingHour
的 Primary Key 不是 Identity Key
这就是为什么它总是被设置为 0
(默认每个 WorkingHour
的 int
) 的值,因此它被复制了。
所以 Id
列 WorkingHour
[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]