1

我一直在使用asp.net核心開發一個商店網站項目提供最新的VS2017的spa模板,並且遇到了我以前沒有遇到的問題,可能是因爲直到現在我的應用程序都非常簡單!Asp.net核心2.0實體類型'X'的實例無法跟蹤,因爲另一個鍵值爲'Id:x'的實例已被跟蹤

我知道問題出在哪裏,我無法修復它。我有一個產品模型,它具有「屬性」集合和「變體」(不同顏色大小等)的集合,並且這些變體也具有屬性,因此如果相同屬性顯示在變體(VAttributes)中,已經在主要的「屬性」我的錯誤

InvalidOperationException異常:已經被追蹤:因爲與 鍵值「2 ID」的另一個實例實體類型 「ProductAttribute」的實例無法被追蹤。在附加現有的 實體時,請確保只附加了一個具有給定鍵值 的實體實例。

最好的答案,我發現在這裏:https://stackoverflow.com/a/19695833/6749293

不幸的是,即使上述檢查我的錯誤,我甚至試圖使附加屬性的列表,如果vattribute匹配的項目之一在列表中,我沒有附加它。事實上,我發現即使我沒有附加(_context.attach())任何vAttributes,它仍然會引發錯誤!

這裏是有問題的代碼:是

public async Task<Product> Create(Product product) 
    { 
     try 
     { 
      foreach (var variation in product.Variations) 
      { 

       foreach (var vAttr in variation.VAttributes) 
       { 

        bool isDetached = _context.Entry(vAttr).State == EntityState.Detached; 
        if (isDetached) 
         _context.Attach(vAttr); 

       } 
      } 
      foreach (var attribute in product.Attributes) 
      { 
       bool isDetached = _context.Entry(attribute).State == EntityState.Detached; 
       if (isDetached) 
        _context.Attach(attribute); 
      } 
      foreach (var category in product.Categories) 
      { 
       _context.Attach(category); 
       _context.Attach(category).Collection(x => x.Children); 
      } 

      _context.Products.Add(product); 

      await Save(); 
      return product; 
     } 
     catch (Exception) 
     { 

      throw; 
     } 


    } 

了3個對象的模型如下:

public class Product 
{ 
    [Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    public string Description { get; set; } 
    public string StockRef { get; set; } 
    public DateTime? LastModified { get; set; } 

    //image needed 
    public ICollection<ProductCategory> Categories { get; set; } 

    public ICollection<ProductAttribute> Attributes { get; set; } 
    public ICollection<ProductVariation> Variations { get; set; } 
    public Product() 
    { 
     Attributes = new List<ProductAttribute>(); 
     Variations = new List<ProductVariation>(); 
     Categories = new List<ProductCategory>(); 
    } 
} 

變化:

public class ProductVariation 
{ 
    [Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public DateTime? LastModified { get; set; } 


    public virtual ICollection<ProductAttribute> VAttributes { get; set; } 
    //needs images 
    public decimal VPrice { get; set; } 
    public string VStockRef { get; set; } 
} 

最後的屬性:

public class ProductAttribute 
{ 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [ForeignKey("AttributeCategory")] 
    public int AttributeCategoryId { get; set; } 
    public virtual AttributeCategory AttributeCategory { get; set; } 


} 

我在搜索時發現的大多數幫助與將單元註冊爲repo的單元或HttpPut方法更加相關,其中代碼檢查是否存在忽略.AsNoTracking(),或者它以某種方式存在第二個實例,我知道第二個例子,我只是不知道如何防止它被追蹤!

編輯:我發現在產品的ProductVariation模型上添加一個外鍵失敗,因爲它只是一個臨時密鑰!?無論如何將它從變體模型中刪除,所以更新了我的代碼。也認爲我會添加我的一個earler失敗的嘗試,導致所有的foreach循環。

  _context.AttachRange(product.Attributes); 
      _context.AttachRange(product.Categories); 
      _context.AttachRange(product.Variations); 
      _context.Add(product); 

回答

0

我相信你可以讓EF來處理跟蹤。

public virtual bool Create(T item) 
    { 
     try 
     { 
      _context.Add(item); 
      _context.SaveChanges(); 
      return true; 
     } 
     catch (Exception e) 
     { 
      return false; 
     } 
    } 

這允許您保存整個對象結構而不用擔心附加項目。

var newProduct = new Product(); 
newProduct.Categories.Add(cat); 
newProduct.Attributes.Add(att); 
newProduct.Variations.Add(vari); 
Create(newProduct); 
+0

可悲的不是。我將現有實體的列表插入到一個新產品中,EF試圖重新添加它們,並且由於已經存在該ID而失敗(我相信它將所有屬性設置爲默認添加),這就是爲什麼我一直在使用附件方法,如果沒有任何ProductVariations的ProductAttribute與Product相同,那麼該方法就可以工作,所以我需要做的是防止任何被跟蹤的事件的第二個實例。 –

相關問題