实体框架两次插入相同的实体

时间:2017-07-18 13:33:03

标签: c# mysql entity-framework

我有以下结构,使用Entity Framework 6与<{1}}进行映射:

enter image description here

这是源数据库:

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.dataCallistHDayName是-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 [..];

     

异常始终发生在同一FooVersionPartFooVersionPart)上。它是2435的第1910个元素。所以EF不会尝试两次插入所有部分,只有一个在中间。

最奇怪的是,它在不久前工作了,它不再起作用,所有相关的东西都没有变化(模式没有变化,没有库更新,代码没有变化)。它在我的一个环境中运行良好,并且在我的开发环境中不能使用相同的代码。

最后一件事,并不是那个Guid特有的。在每次尝试时,Guid都是不同的(不是其他输入,因此它仍然在dim.proran.db.tmp.dataCallistHDay上失败),并且在每次尝试时我都会得到相同的错误。

您是否知道可能导致这种情况的原因?

1 个答案:

答案 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 ' 不会发现的副本,但会被数据库引擎捕获。一个简单的解决方案是在分组之前修剪数据,这是一个很好的习惯,特别是手动输入的数据。

相关问题