簡體   English   中英

實體類型的實例……無法跟蹤,因為已經在跟蹤具有相同鍵的此類型的另一個實例

[英]The instance of entity type … cannot be tracked because another instance of this type with the same key is already being tracked

給定一個使用 Entity Framework Core 和 SQL 數據庫的 ASP.NET Core webapp。

嘗試更新數據庫中的實體時,絕對簡單的操作是拋出此異常。 首先被生產中的錯誤報告注意到。

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("Group")] EditViewModel model)
{
    if (id != model.Group.Id) return NotFound();

    if (!ModelState.IsValid) return View(model);

    _context.Update(model.Group);
    await _context.SaveChangesAsync();

    return RedirectToAction("Index");
}

在該行拋出異常: _context.Update(model.Group);

InvalidOperationException:無法跟蹤實體類型“組”的實例,因為已在跟蹤具有相同鍵的此類型的另一個實例。 添加新實體時,對於大多數鍵類型,如果未設置鍵(即,如果鍵屬性為其類型分配了默認值),將創建一個唯一的臨時鍵值。 如果您為新實體顯式設置鍵值,請確保它們不會與現有實體或為其他新實體生成的臨時值發生沖突。 附加現有實體時,確保只有一個具有給定鍵值的實體實例附加到上下文。

顯然沒有其他實例。 當我在該行上使用斷點停止代碼並擴展_context.Group對象的 Results 屬性時,我能夠在我的開發環境中重現異常: _context.Group 對象的展開結果屬性的屏幕截圖 可以理解,在展開結果時,它會加載需要更新的實例,這就是拋出異常的原因。 但是部署的生產環境呢?

感謝您的幫助!

UPDATE1 Group模型:

public class Group
{
    [Display(Name = "ID")]
    public string Id { get; set; }

    public virtual Country Country { get; set; }

    [Required]
    [Display(Name = "Country")]
    [ForeignKey("Country")]
    public string CountryCode { get; set; }

    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }
}

UPDATE2基於@Mithgroth 的回答,我能夠覆蓋函數_context.Update()以便每次使用它時都不需要 try-catch:

public interface IEntity 
{
    string Id { get; }
}

public override EntityEntry<TEntity> Update<TEntity>(TEntity entity)
{
    if (entity == null)
    {
        throw new System.ArgumentNullException(nameof(entity));
    }

    try
    {
        return base.Update(entity);
    }
    catch (System.InvalidOperationException)
    {
        var originalEntity = Find(entity.GetType(), ((IEntity)entity).Id);
        Entry(originalEntity).CurrentValues.SetValues(entity);
        return Entry((TEntity)originalEntity);
    }
}

請改用以下內容:

var group = _context.Group.First(g => g.Id == model.Group.Id);
_context.Entry(group).CurrentValues.SetValues(model.Group); 
await _context.SaveChangesAsync();

異常可能由許多不同的場景引起,但問題是,您正在嘗試更改已標記為不同的對象的狀態。

例如,這將產生相同的異常:

var group = new Group() { Id = model.Id, ... };
db.Update(group);

或者你可能已經分離了 N 層孩子,這都是可能的。

這確保您只是覆蓋現有實體的值。

謝謝大家的想法。 我在沒有異常的情況下在我的上下文中創建了這個被覆蓋的函數,恕我直言,這是一種更好的方法。 此外,使用定義的模型檢索主鍵名稱。

此外,它是 EntityFramework 3.0 .NET Core

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System.Linq;



    public override EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class
    {
        if (entity == null)
        {
            throw new System.ArgumentNullException(nameof(entity));
        }

        var type = entity.GetType();
        var et = this.Model.FindEntityType(type);
        var key = et.FindPrimaryKey();

        var keys = new object[key.Properties.Count];
        var x = 0;
        foreach(var keyName in key.Properties)
        {
            var keyProperty = type.GetProperty(keyName.Name, BindingFlags.Public | BindingFlags.Instance);
            keys[x++] = keyProperty.GetValue(entity);
        }

        var originalEntity = Find(type, keys);
        if (Entry(originalEntity).State == EntityState.Modified)
        {
            return base.Update(entity);
        }

        Entry(originalEntity).CurrentValues.SetValues(entity);
        return Entry((TEntity)originalEntity);
    }

暫無
暫無

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

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