【发布时间】:2017-09-01 07:08:51
【问题描述】:
我一直在做一个商店站点项目,使用最新的 VS2017 提供的 asp.net core spa 模板,并且遇到了一个我以前没有遇到过的问题,可能是因为到目前为止我的应用程序非常简单!
我知道问题出在哪里,但我无法解决。我有一个产品模型,它有一个“属性”集合和一个“变体”集合(不同的颜色大小等),这些变体也有属性,所以如果相同的属性出现在变体(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);
【问题讨论】:
标签: entity-framework asp.net-core asp.net-core-webapi asp.net-core-2.0