[英]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.