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