我一直在使用最新的VS2017提供的asp.net核心水疗模板开展一个商店网站项目,并且遇到了我以前没有的问题,可能是因为到目前为止我的应用程序相当简单!
我知道问题是什么,在哪里,我无法修复它。我有一个产品模型,其中包含"属性"以及" Variations" (不同的颜色大小等)和那些变体也有属性,所以如果相同的属性出现在变体(VAttributes)中,就像主要的"属性"我收到了错误
InvalidOperationException:实体类型的实例 ' ProductAttribute'无法跟踪因为另一个实例 关键值' Id:2'已被跟踪。附加现有的 实体,确保只有一个具有给定键值的实体实例 附上。
我找到的最佳答案是: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模型上的外键添加到正在创建的产品中失败,因为它只是一个临时密钥!?无论如何从变异模型中删除它,所以更新了我的代码。还以为我添加了一个我的失败尝试,这导致了所有的foreach循环。
_context.AttachRange(product.Attributes);
_context.AttachRange(product.Categories);
_context.AttachRange(product.Variations);
_context.Add(product);
答案 0 :(得分: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);