尝试更新Db时出现相同的主键错误

时间:2014-10-25 14:52:43

标签: c# entity-framework

我的应用是电影收藏经理。我创建了一个EF模型 - 第一个db。我有一个Person实体,其Pictures属性是Picture实体的集合。

鉴于电影标题,我从网上获取所有信息并获得演员(= Person entities)的列表。对于每个人,我创建了一个新的List<Picture>,其中包含一个新的Picture对象,其中包含从网络抓取的图片。

对于每个PersonPictures属性中唯一的图片具有相同的Id属性(因为它们都是独立的List<Picture>)。因此,当我尝试更新数据库时,会抛出DbUpdateException

  

多个添加的实体可能具有相同的主键

易于理解,但我一直认为EF会自己处理所有这些内容(即将Picture表中的每个Person.Pictures集合中的每个Picture赋予它一个不同的内容ID)。

显然并非如此。为了解决这个问题,我必须在Picture表格中直接创建一个Picture表格,根据我的模型,这对我没有任何意义:图片附在一个人身上,所以我创建它当我创建一个Person对象时。如果没有,使用模型优先方式有什么好处?

我错过了处理这件事的事吗?

PS:请参阅here我简化模型的图片,以说明所有内容是如何互连的。

更清楚一点,这里是流程的运行方式(我将负责解析HTML代码的代码放在一边,从网页上获取信息; multipleItems包含一组被解析的html div):

foreach (var act in multipleItems)
{
     Person myact = new Person();
     List<Picture> mylistpics = new List<Picture>();
     Picture mypic = new Picture();
     mypic.Data = /*[...code for creating image from web data...]*/
     mylistpics.Add(mypic);
     myact.Pictures = mylistpics;
     //[...]code for grabbing name of actor in webpage[...]
     myact.FirstName = names[0];
     myact.Name = names[1];
     mypersons.Add(myact);
}

mymovie.Actors = mypersons;

所以你可以看到,重要的是,我将图片添加到Person的{​​{1}}属性中。因此每个Pictures都有自己独立的图片集合:这是正常的,对于每个Person的集合,添加的图片的Id为0。

当循环结束时,我会影响Person列表到我窗口当前DataContext(电影对象)的Actors属性。

然后,它在mypersons调用(将整个Dbcontext.SaveChanges();对象保存到数据库)上抛出异常。

转到here以查看图片 - 人员关联的属性窗格。

2 个答案:

答案 0 :(得分:0)

您的数据库似乎没有将图片ID作为标识字段,因此,如果不设置Id,则默认值(可能为0)会导致所有相同的主键。将IDENTITY添加到数据库表并更新EF模型后,您应该注意到该列将Id字段的StoreGeneratedPattern属性设置为identity,以便将其配置为使用生成的主数据库来自身份证明的密钥。

答案 1 :(得分:0)

您很难让EF跟随代码的实体关系。试试这个,这对人类和EF都更具可读性:

Person myact = new Person
        {
          FirstName = names[0],
          Name = name[1],
          Pictures = new List<Picture>
                     {
                       new Picture { Data = previouslyComputedData }
                     }
        }

此外(或者替代地),您还可以为Picture个对象明确指定不同的ID(负数以确保没有任何干扰)。 EF会在SaveChanges上覆盖它们:

int picId = -1;
...
          new Picture { Id = picId--, Data = previouslyComputedData }

更新:也许EF并不喜欢将这些演员全部添加进去。尝试在每次Person创建后保存更改:

Person myact = new Person { ... }
mymovie.Actors.Add(myact);
// SaveChanges();