我有以下型号: -
public abstract class BaseClass
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id
{
get;
set;
}protected BaseClass()
{
if (Guid.Empty==Id)
{
Id = LongGuid.NewGuid();
}
}
}
}
public class Product : BaseClass
{
// other properties like name and price.
private Recipe _recipe;
public virtual Recipe Recipe
{
get
{
return this._recipe;
}
set
{
this._recipe = value;
}
}
private InventoryItem _inventoryItem;
public virtual InventoryItem InventoryItem
{
get
{
return this._inventoryItem;
}
set
{
this._inventoryItem = value;
}
}
public class InventoryItem : BaseClass
{
// Name and value
}
public class Recipe : BaseClass
{
// Name and value
}
public class DataContext : DbContext
{
public DbSet<Recipe> Recipes { get; set; }
public DbSet<InventoryItem> InventoryItems { get; set; }
public DbSet<Product> Product { get; set; }
}
我保存如下: -
this._workspace.Update(Model);
this._context.SaveChanges();
当我用InventoryItem和Recipe创建产品时,它的效果很好。
但是当我创建没有InventoryItem和Recipe的产品并保存在数据库中之后我尝试使用新的InventoryItem()和新的Recipe()更新产品时出现以下错误: -
保存不公开外键的实体时发生错误 他们关系的属性。 EntityEntries属性将 返回null,因为无法将单个实体标识为源 例外。可以在保存时处理异常 通过在实体类型中公开外键属性更容易。看到 InnerException以获取详细信息。
内部错误: -
存储更新,插入或删除语句会影响意外 行数(0)。自那以后,实体可能已被修改或删除 实体已加载。看到 http://go.microsoft.com/fwlink/?LinkId=472540了解有关的信息 理解和处理乐观并发异常。
答案 0 :(得分:1)
您收到此错误的原因是,EF无法确定如何将您的产品与您的配方和InventoryItem相关联。要解决此问题,请暂时删除您的InventoryItem,并按预期保持产品和配方的持久性。
使用EF 6和Core,您可以选择在父实体中定义FK字段,并将其指定为您引用的子实体的FK。
例如,使用代码优先注释:
public class Product
{
[Key]
public Guid ProductId {get; set;}
[ForeignKey("RecipeId")]
public virtual Recipe Recipe {get; set;}
public Guid RecipeId {get; set;}
// ...
}
或者,您可以通过实体类型配置使用配置或覆盖DbContext的OnModelCreating以使用.HasForeignKey()流畅方法建立外键。
如果您不小心,以这种方式映射FK可能会引发问题,因为您现在已经引用了食谱实体和单独的FK引用,并且必须确保它们保持同步。
或者使用EF 6,您可以映射FK的列,而不使用实体类型配置中的.Map()/ w .MapKey()或DbContext的OnModelCreating来声明属性。从我所读到的关于EF Core的内容来看,这还不是一个选择。
配方参考工作完成后,对于InventoryItem,它将是相同的。
我在这篇文章中介绍了使用引用与FK(而不是两者)的内容: http://www.practicagility.com.au/2017/10/27/ef-a-1st-class-citizen-part-4-using-references-vs-keys/