我有以下结构,使用Entity Framework 6
与<{1}}进行映射:
这是源数据库:
Database First principle
在我的代码中,我正在创建一个像这样的新foo:
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);
我在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();
:
为'PRIMARY'键重复输入'dim.proran.db.tmp.dataCallistHDay -9e6620f4-227d-44de-b781-5fd67'
当EF试图插入其中一个FooVersionPart时,更具体地发生错误(SaveChanges
是该部分的dim.proran.db.tmp.dataCallistHDay
而Name
是-truncated- 9e6620f4-227d-44de-b781-5fd67
那部分)。
我绝对肯定RefFooVersionGuid
没有重复,也没有数据库。
这是生成的SQL:
INSERT INTO
sourceParts
[..];INSERT INTO
Foo
[..];INSERT INTO
FooVersion
[..];INSERT INTO
FooVersionPart
[..];INSERT INTO
FooVersionPart
[..];INSERT INTO
FooVersionPart
[..];等
异常始终发生在同一FooVersionPart
(FooVersionPart
)上。它是2435的第1910个元素。所以EF不会尝试两次插入所有部分,只有一个在中间。
最奇怪的是,它在不久前工作了,它不再起作用,所有相关的东西都没有变化(模式没有变化,没有库更新,代码没有变化)。它在我的一个环境中运行良好,并且在我的开发环境中不能使用相同的代码。
最后一件事,并不是那个Guid特有的。在每次尝试时,Guid都是不同的(不是其他输入,因此它仍然在dim.proran.db.tmp.dataCallistHDay
上失败),并且在每次尝试时我都会得到相同的错误。
您是否知道可能导致这种情况的原因?
答案 0 :(得分:1)
异常消息(Duplicate entry 'dim.proran.db.tmp.dataCallistHDay -9e6620f4-227d-44de-b781-5fd67' for key 'PRIMARY'
)与其引用的表(PRIMARY KEY ('Name', 'RefFooVersionGuid')
)的主键相结合,告诉我们您正在尝试将重复数据插入表中,特别是多个{{1具有相同名称的s。
现在您说您对源数据进行了重复检查,但您可能不知道的是,许多(全部?)SQL数据库不将尾随空格计为记录的一部分。例如,此查询实际上将返回一条记录:
FooVersionPart
因此,正如您所确认的那样,您的数据确实存在C#SELECT 1
WHERE 'abc' = 'abc '
不会发现的副本,但会被数据库引擎捕获。一个简单的解决方案是在分组之前修剪数据,这是一个很好的习惯,特别是手动输入的数据。