我的应用是电影收藏经理。我创建了一个EF模型 - 第一个db。我有一个Person
实体,其Pictures
属性是Picture
实体的集合。
鉴于电影标题,我从网上获取所有信息并获得演员(= Person entities)
的列表。对于每个人,我创建了一个新的List<Picture>
,其中包含一个新的Picture
对象,其中包含从网络抓取的图片。
对于每个Person
,Pictures
属性中唯一的图片具有相同的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以查看图片 - 人员关联的属性窗格。
答案 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();