簡體   English   中英

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 語句。

所以你有兩個選擇:

  1. 在您的檢索查詢中添加.AsNoTracking()以便您將執行無跟蹤查詢,並且不會將實體分別添加到數據庫上下文中。 然后您將在“斷開連接的場景”中工作,您可以使用 db context Update()方法;

  2. 通過逐個字段映射來更改UpdateChild方法,因此更改實體中的字段會將其EntityState設置為Modified 然后完全刪除_dbContext.Update(item)因為SaveChanges()將完成整個工作。

另一件要提的事情 - 在循環中執行SaveChanges()通常不是一個好主意。 這意味着您向數據庫發送 (n) 個查詢,其中 (n) 是記錄數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM