![](/img/trans.png)
[英]Add or Update child entities when updating a parent entity in Entity Framework Core
[英]Entity Framework Core Update child entities problem
在我的 ASP.NET Core 2.2 中。 MVC 項目我有一個主從表單,用於編輯一個 PARENT 表,該表也有一個子實體列表(存儲在 CHILD 表中)。
當我在表單上保存修改時,我首先將更改保存到父實體,然后運行以下方法來更新相應的子實體:
private void UpdateChildList(ParentModel model)
{
// lists
var listOld = _parents.Get(model.IdParent).ListChilds;
var listNew = model.ListChilds;
var listNewInt = from x in listNew select x.IdChild;
// 1. remove deleted
var deleteList = new List<int>();
deleteList = listOld.Where(t => !listNewInt.Contains(t.IdChild)).Select(x => x.IdChild).ToList();
foreach (var d in deleteList)
{
var item = listOld.Where(x => x.IdChild == l).First();
_parents.DeleteChild(item);
}
// 2. update existing
var list = from x in listNew
where x.IdChild > 0
select x;
foreach (var item in list)
{
_parents.UpdateChild(item);
}
// 3. add new
list = from x in listNew
where x.IdChild == 0
select x;
foreach (var item in list)
{
_parents.AddChild(item);
}
}
1.刪除作品 OK & 3.添加作品 OK,但是2. UPDATING 產生以下錯誤:
InvalidOperationException:無法跟蹤實體類型“Child”的實例,因為已經在跟蹤具有相同鍵值 {'IdChild'} 的另一個實例。 附加現有實體時,請確保僅附加一個具有給定鍵值的實體實例。 考慮使用“DbContextOptionsBuilder.EnableSensitiveDataLogging”來查看沖突的鍵值。
注意:我正在使用service.AddScoped
在我的 Startup class 中添加服務。
編輯:我正在從我的 HTTPPost(在控制器中)添加代碼:
[HttpPost]
public IActionResult Edit(ParentModel model)
{
// valid check
if (!ModelState.IsValid)
{
/// ... some lists for dropdowns here
return View(model);
}
var item = _parents.Get(model.IdParent);
item.Field1 = model.Field1;
// ... and other fields
// update parent
_parents.Update(item);
// update Child list
UpdateChildList(model);
return RedirectToAction("Index");
}
EDIT2:添加我的刪除/更新/添加子記錄的代碼
public void AddChild(Child item)
{
_dbContext.Add(item);
_dbContext.SaveChanges();
}
public void UpdateChild(Child item)
{
_dbContext.Update(item);
_dbContext.SaveChanges();
}
public void DeleteChild(Child item)
{
_dbContext.Remove(item);
_dbContext.SaveChanges();
}
當你這樣做時:
var listOld = _parents.Get(model.IdParent).ListChilds;
實體框架從上下文中檢索信息並開始跟蹤這些實體,當您這樣做時:
_parents.UpdateChild(item);
你調用:
_dbContext.Update(item);
在另一邊嘗試再次將此實體附加到上下文並將其EntityState
設置為已Modified
,因此您會遇到異常。
當您從數據庫中檢索信息然后使用它時,您處於所謂的“連接場景”中,並且實體框架上下文跟蹤所有檢索到的實體。 一旦您修改了此實體的某些數據,上下文就會將其EntityState
設置為Modified
,因為執行了修改。 因此,您可以調用SaveChanges()
方法,它在數據庫中構建並執行 Update 語句。
所以你有兩個選擇:
在您的檢索查詢中添加.AsNoTracking()
以便您將執行無跟蹤查詢,並且不會將實體分別添加到數據庫上下文中。 然后您將在“斷開連接的場景”中工作,您可以使用 db context Update()
方法;
通過逐個字段映射來更改UpdateChild
方法,因此更改實體中的字段會將其EntityState
設置為Modified
。 然后完全刪除_dbContext.Update(item)
因為SaveChanges()
將完成整個工作。
另一件要提的事情 - 在循環中執行SaveChanges()
通常不是一個好主意。 這意味着您向數據庫發送 (n) 個查詢,其中 (n) 是記錄數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.