我想添加实体付款对象,其中包含EXISTING Currency对象到EF数据库:
public Payment()
{
int Id {get;set;}
public int Value {get;set;}
public Currency SelectedCurrency{get;set;}
}
public Currency()
{
int Id {get;set;}
string Name;
}
假设我已将现有货币附加到新实体Payment()。当我添加这样的实体Payment()时,出现错误
违反PRIMARY KEY约束'PK_dbo.Currency'。无法在对象'dbo.MwbeCurrency'中插入重复键。重复键值为(GBP)。\ r \ n语句已终止。“}
如何添加附加现有较低级别实体的更高级别实体?
我添加实体的代码是:
public virtual TEntity Add(TEntity entity)
{
return DbSet.Add(entity);
}
public void SaveChanges()
{
Context.SaveChanges();
}
答案 0 :(得分:2)
我怀疑您使用与检索Currency
的实例不同的实例检索Payment
并执行了类似的操作:
payment.Currency = retrievedCurrency;
因此,Payment
上下文Currency
是一个新对象,并试图将其持久化。由于它已经存在,因此您将收到PRIMARY KEY违规。
如果您想正确保留Payment
,请添加以下行:
if (payment.Currency != null && payment.Currency.Id != 0)
{
context.Entry(payment.Currency).State = EntityState.Unchanged;
}
虽然如果您使用相同的上下文检索Payment
和Currency
可能会更干净,因此您可以适当地保留它们。
答案 1 :(得分:0)
调用DbSet.Add(entity)
会为持久性添加整个图表,这意味着它将遍历entity
的所有导航属性,并将每个状态设置为EntityState.Added
。
虽然另一个答案可能有效,但更好的方法是更改添加对象的方式,并明确说明要添加/更新/等的实体。
为此,请更改:
public virtual void Add(TEntity entity)
{
DbSet.Add(entity);
}
要:
public virtual void Add(TEntity entity)
{
context.Entry(entity).State = EntityState.Added;
}
这将仅添加提供的实体。如果您的某个导航属性对象也是新的,那么您也可以在其上调用.Add(entity)
。
如果您确实需要在其他情况下添加整个图形,您可以添加一个与原始图形一样的方法,但有一个更好的名称来表示它的功能:
public virtual void AddGraph(TEntity entity)
{
DbSet.Add(entity);
}
祝你好运
<强>更新强>
此外,由于看起来您正在使用存储库,我更喜欢通过设置context.Configuration.AutoDetectChangesEnabled = false;
来禁用自动检测更改如果您修改了要保留的实体的属性,则需要设置状态像这样修改的实体:
public virtual void Update(TEntity entity)
{
context.Entry(entity).State = EntityState.Modified;
}