[英]Entity Framework: A referential integrity constraint violation on many to many relationship
嘿,我有一个带有大量进程内缓存和实体框架的应用程序。 当我想对实体进行更新时,我会重新附加缓存的副本。 我跟踪我在上下文的生命周期中附加的所有东西,所以我不会尝试附加它们两次。
我在附加时发生错误(在大多数情况下很少见,这工作正常并且非常快),它说以下内容:
发生引用完整性约束冲突:定义引用约束的属性值在关系中的主体对象和依赖对象之间不一致。
我仔细查看了看起来很正常的实体。 我认为这个问题是由于修复运行时外键的附加/分离造成的。
有没有一种好方法可以获取有关此错误的更多信息,或者它是否可以由于实体位于 state 而不是 EF 预期的其他原因而发生?
编辑:数据库图(注意我使用的是 codefirst 我只是使用 EDMX 工具来制作图表,为了简单起见,我还从 model 中删除了一堆常规属性)
除了多对多关系之外,您显然在 model 中拥有的Person
和Location
之间的一对多关系可能会发生错误。 例如下面的代码会抛出异常:
using (var context = new MyContext())
{
var person = new Person
{
CurrentLocationId = 1,
CurrentLocation = new Location { Id = 2 }
};
context.People.Attach(person); // Exception
}
“定义引用约束的属性值”是外键属性值CurrentLocationId
和主键值CurrentLocation.Id
。 如果这些值不同,则抛出异常。 (虽然CurrentLocation
为null
是允许的。)
在我看来,只能为外键关联抛出此异常,因为只有对于这种类型的关联,您才具有在 model 中定义引用约束的属性。它不能为独立关联抛出。 由于每个多对多关系都是一个独立的关联(模型中没有外键属性),我的猜测是错误与您的多对多关系无关,而是与一对多关系有关。
我遇到了一个非常相似的异常:
"A referential integrity constraint violation occurred:
The property value(s) of 'ObjectA.PropertyX' on one end of a relationship
do not match the property value(s) of 'ObjectB.PropertyY' on the other end."
原因是这样的:web API 的客户端发送了一个包含整个 object 的 PUT 请求,包括导航属性(在此示例中,ObjectA(更准确地说是 ObjectB.ObjectA)是一个导航属性,完全由客户端提供)。 发生这种情况是因为客户端从服务器接收到整个 object 并将其按原样弹回服务器并进行微小更改。
另一方面,ObjectB.PropertyY 刚刚被更改(这是 PUT 请求的首要原因)。
由于 ObjectB.PropertyY 是对同一个 object ObjectA(外键)的引用,因此 EF 尝试对此进行协调,但因上述异常而失败。
解决方案很简单:
ObjectB.ObjectA = null;
在 SaveChanges() 完全解决这个问题之前。
我希望这可以帮助别人。
我刚刚遇到了同样的问题,我的解决方案是我已将映射添加到关联,然后设置引用约束。
为了解决这个问题,我必须打开关联的映射 window,并且有一个删除映射的链接。 一旦完成映射详细信息 window 然后说不允许映射。添加引用约束似乎会留下任何映射。
认为可能值得发布,以防其他人将来寻找此错误消息的解决方案。
@LukeMcGregor 嗨,
我想我可以提供与有同样问题的人不同的观点。
在我执行了所有必要的检查之后,我可以说我更愿意得到这个错误。
因为在我的场景中:我想包含一个导致不匹配错误的 object。 它是您场景中的位置 object。 如果我添加一个带有 ID 的 object,我会收到此错误,因为之前的 object(未更新的那个)中的 ID 与更新后的 ID 不匹配。
但这不是什么大问题。 作为解决方案; 如果还在UI端,object如果还存在的话,可能还是会被包含进去。
当您收到用户的更新请求时,您将清空 object。 (= Null) 或者,您将使用用户在服务端更新(附加、修改...等等)之前更新的 ID 更新 object,并以这种方式更新它。
而已。 它可以保持数据库和图表中的原样。
要添加到@Slauma 的答案,不仅仅是在将对象添加到您的上下文时。 对于您的示例,如果您在 Person 中编辑 CurrentLocationId,则还需要编辑 Person object 中嵌入的 CurrentLocation object。EF 将自动填充 CurrentLocation object,因为 CurrentLocationId 在 CurrentLocation 的表中有一个外键。 当您在不更新 CurrentLocation object 的情况下编辑 CurrentLocationId 时,它们会变得不同步。 这就是导致本例异常的原因。
因此,假设您需要更新 Person 对象的 CurrentLocationId。 我们假设您预取了 Person 数据和 Location 数据。
public class DbData
{
List<Person> PersonList;
List<Location> LocationList;
public DbData()
{
using (var context = new MyContext())
{
PersonList = context.Persons.ToList();
LocationList = context.Locations.ToList();
}
}
public void UpdatePersonLocation(Person person, int newLocationId)
{
using (var context = new MyContext())
{
var location = LocationList.Where(l=>l.id==newLocationId).Single();
//you need to update both the id and the location for this to not throw the exception
person.CurrentLocationId == newLocationId;
person.CurrentLocation == location;
context.Entry(person).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
}
//or if you're giving it the location object...
public void UpdatePersonLocation(Person person, Location location)
{
using (var context = new MyContext())
{
//you need to update both the id and the location for this to not throw the exception
person.CurrentLocationId == location.id;
person.CurrentLocation == location;
context.Entry(person).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
}
}
我刚遇到这个问题,想出了一个非常快速的解决方案。 我的问题是一张多对多表。
Public class Pictures_Tag
{
[Key]
[Column(Order = 0)]
[ForeignKey("Picture")]
public Int16 Picture_ID { get; set; }
[Key]
[Column(Order = 1)]
[ForeignKey("ImageTag")]
public Int16 ImageTag_ID { get; set; }
public virtual Picture Picture { get; set; }
public virtual ImageTag ImageTag { get; set; }
}
我在分配Picture = db.Pictures...
的位置添加了行,然后它工作正常(不确定为什么)
[HttpPost]
public ActionResult Edit2(WebSiteEF2017C.Models.Pictures_Tag p)
{
using (var db = new thisModel(Session["org"].ToString())
{
p.Picture = db.Pictures.Where(z => z.ID == p.Picture_ID).FirstOrDefault();
db.Pictures_Tags.Attach(p);
db.Entry(p).State = EntityState.Modified;
db.SaveChanges();
return View(db.Pictures_Tags.Include(x => x.Picture)
.Where(n => n.Picture_ID == p.Picture_ID & n.ImageTag_ID == p.ImageTag_ID).FirstOrDefault());
}
}
尝试将任何子 class object 设置为 null MainObject.SubObject1 = null; Person.Address=null; // 地址 Object 为 null 而不是 id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.