尝试更新Db时出现相同的主键错误
本文关键字:错误 更新 Db | 更新日期: 2023-09-27 18:27:52
我的应用程序是一个电影收藏管理器。我创建了一个EF模型第一个数据库。我有一个具有Pictures
属性的Person
实体,它是Picture
实体的集合。
给定一个电影标题,我从网上获取所有信息,并获得演员(= Person entities)
的列表。对于它们中的每一个,我都创建了一个新的List<Picture>
和一个新Picture
对象,其中包含从网络上抓取的图片。
对于每个Person
,Pictures
属性中的唯一图片具有相同的Id属性(因为它们都是独立的List<Picture>
)。所以当我尝试更新数据库时,会抛出一个DbUpdateException
,上面写着
多个添加的实体可能具有相同的主密钥
很容易理解,但我一直认为EF会自己处理所有这些事情(也就是说,将每个Person.Pictures
集合中的每个Picture
放在Picture
表中会给它一个不同的Id)。
显然情况并非如此。为了处理这个问题,我必须在Picture
表中直接创建一个Picture
,根据我的模型,这对我来说毫无意义:一张照片被附加到一个人身上,所以我在创建Person
对象时创建它。如果不是,那么使用模型优先的方式有什么好处?
我是不是错过了处理这个问题的方法?
附言:请看我简化模型的图片,说明所有的东西是如何相互连接的。
更清楚地说,流程是如何运行的(我把负责解析html代码的代码放在一边,以便从网页中获取信息;multipleItems
包含一组经过解析的htmldiv):
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
的Pictures
属性中。因此,每个Person
都有自己独立的图片集合:对于每个Person
的集合,添加的图片Id为0是正常的。
循环结束后,我会将mypersons
列表影响到窗口(电影对象)的当前DataContext的Actors属性。
然后,在Dbcontext.SaveChanges();
调用(将整个Movie
对象保存到数据库)上抛出异常。
转到此处查看"图片人关联"的属性窗格。
您的数据库似乎没有图片Id作为标识字段,因此如果不设置Id,默认值(可能为0)将导致所有相同的主键。将IDENTITY添加到数据库表并更新EF模型后,您应该注意到该列将Id字段的StoreGeneratedPattern
属性设置为identity
,以便将其配置为使用标识插入中生成的主键。
您让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();