实体框架两次插入相同的实体[重复]
Posted
技术标签:
【中文标题】实体框架两次插入相同的实体[重复]【英文标题】:Entity Framework inserts the same entity twice [duplicate] 【发布时间】:2017-12-23 09:53:19 【问题描述】:我有以下结构,使用Database First principle
映射到Entity Framework 6
:
这里是源数据库:
CREATE TABLE `Foo` (
`Guid` VARCHAR(36),
`Name` VARCHAR(500) NOT NULL,
`Author` VARCHAR(100) NOT NULL,
PRIMARY KEY (`Guid`),
UNIQUE KEY `unique_fooname` (`Name`,`Author`));
CREATE TABLE `FooVersion` (
`Guid` VARCHAR(36),
`Version` INT,
`RefFooGuid` VARCHAR(36) NOT NULL,
PRIMARY KEY (`Guid`),
UNIQUE KEY `unique_fooversion` (`Version`,`RefFooGuid`),
CONSTRAINT `fk_foo_version`
FOREIGN KEY (`RefFooGuid`)
REFERENCES `Foo` (`Guid`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
CREATE TABLE `FooVersionPart` (
`Name` VARCHAR(250) NOT NULL,
`RefFooVersionGuid` VARCHAR(36) NOT NULL,
PRIMARY KEY (`Name`, `RefFooVersionGuid`),
INDEX `fk_fooversion_fooversionpart_idx` (`RefFooVersionGuid` ASC),
CONSTRAINT `fk_fooversion_fooversionpart`
FOREIGN KEY (`RefFooVersionGuid`)
REFERENCES `FooVersion` (`Guid`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
在我的代码中,我正在创建一个新的 foo,如下所示:
var dbContext = new DbContext();
var newVersion = new FooVersion();
newVersion.Guid = Guid.NewGuid().ToString()
newVersion.Parts = sourceParts.Select(s => new FooVersionPart
Name = s.Name,
RefFooVersionGuid = newVersion.Guid
.ToList();
var foo = new Foo
Author = "Me"
Guid = Guid.NewGuid().ToString(),
Name = "Foo"
;
dbContext.Foos.Add(foo);
foo.Versions.Add(newVersion);
dbContext.SaveChanges();
我在SaveChanges
期间收到以下错误:
键“PRIMARY”的重复条目“dim.proran.db.tmp.dataCallistHDay -9e6620f4-227d-44de-b781-5fd67”
当 EF 尝试插入其中一个 FooVersionPart 时,错误会更具体地发生(dim.proran.db.tmp.dataCallistHDay
是该部分的 Name
,9e6620f4-227d-44de-b781-5fd67
是该部分的 -truncated- RefFooVersionGuid
)。
我绝对确定sourceParts
没有重复,也没有在数据库中。
这是生成的 SQL:
插入
Foo
[..];插入
FooVersion
[..];插入
FooVersionPart
[..];插入
FooVersionPart
[..];插入
FooVersionPart
[..];插入
FooVersionPart
[..];等等
异常总是发生在同一个FooVersionPart
(dim.proran.db.tmp.dataCallistHDay
) 上。它是 2435 的第 1910 个元素。因此 EF 不会尝试将所有部分插入两次,而只是在中间插入一个。
最奇怪的是,它在不久前就可以工作了,但它不再工作了,所有相关的东西都没有变化(架构没有变化,库没有更新,代码没有变化)。它在我的一个环境中运行良好,但在我的开发环境中无法使用相同的代码。
最后一件事,它不是特定于那个 Guid。每次尝试时,Guid 都是不同的(不是其他输入,因此在 dim.proran.db.tmp.dataCallistHDay
上仍然失败),并且每次尝试时我都会遇到相同的错误。
您知道是什么原因造成的吗?
【问题讨论】:
看不到您的代码或源数据,我们如何才能真正提供帮助? 如何向您展示我正在插入的 2435 个元素?我向您展示了与我的代码相关的内容。如果您想要更具体的元素,请询问。 你需要自己调试。看看报错,dim.proran.db.tmp.dataCallistHDay
是什么?问题中没有提到该对象。
@DavidG 我没有清楚地解释错误发生在哪里。我试图在上次编辑中更清晰。
也许下一次当你有多个人建议你有重复时,不要这么快就假设你没有重复! :)
【参考方案1】:
异常消息 (Duplicate entry 'dim.proran.db.tmp.dataCallistHDay -9e6620f4-227d-44de-b781-5fd67' for key 'PRIMARY'
) 结合它所引用的表的主键 (PRIMARY KEY ('Name', 'RefFooVersionGuid')
) 告诉我们您正在尝试向表中插入重复数据,特别是多个 FooVersionPart
s 具有相同的姓名。
现在您说您已经对源数据进行了重复检查,但您可能不知道有很多(全部?)SQL 数据库不将尾随空格计为记录的一部分。例如这个查询实际上会返回一条记录:
SELECT 1
WHERE 'abc' = 'abc '
因此,正如您所确认的,您的数据确实有重复项,C#GroupBy
不会发现这些重复项,但会被数据库引擎捕获。一个简单的解决方案是在分组之前修剪数据,这是一个很好的习惯,尤其是手动输入的数据。
【讨论】:
如你所说,被忽略尾随空格的 mysql 抓住了......以上是关于实体框架两次插入相同的实体[重复]的主要内容,如果未能解决你的问题,请参考以下文章