如何添加附加现有的实体

时间:2015-04-24 15:00:05

标签: entity-framework

我想添加实体付款对象,其中包含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();            
        }

2 个答案:

答案 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;
}

虽然如果您使用相同的上下文检索PaymentCurrency可能会更干净,因此您可以适当地保留它们。

答案 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;
}