1

我在数据库中添加了一行,并返回一个不同的上下文来更新它。我有这个类:实体框架更新现有对象

public abstract partial class DataManager<I, C> 
    where C : class, IDomainObject, I, new() where I : IDomainObject 

C可能是一个EntityObject,但这个类不知道。

我保存看起来是这样的:

public virtual bool Save(I _item) 
    { 
     bool rc = true; 
     try 
     { 
     var set = m_Context.GetObjectSet<I, C>(); 
     ObjectStateEntry stateEntry = null; 
     if(! m_Context.ObjectStateManager.TryGetObjectStateEntry((C) _item, out stateEntry)) 
     { 
      if(_item is EntityObject) 
      { 
        if (_item.IsNew) 
        { 
         set.AddObject((C) _item); 
        } 
        else 
        { 
         try 
         { 
          set.Attach((C) _item); 
         } 
         catch(Exception ex) 
         { 
          set.ApplyCurrentValues((C) _item); 
         } 

等等...

在我的测试情况下,stateEntry不TryGetObjectStateEntry发现。然而,它是一个EntityObject,它不是新的(IsNew是我的标志),所以它到达了其他地方。这里是我的问题:set.Attach抛出这个错误

“ObjectStateManager中已存在具有相同键的对象,ObjectStateManager无法使用相同键追踪多个对象。

,并在第二天瞬间,ApplyCurrentValues抛出这样一句:

“与所提供的对象的密钥匹配无法在ObjectStateManager找到一个关键的对象验证提供的键值。对象匹配必须应用更改的对象的键值。“

这些都是真的吗?

更多信息:

_item被在另一背景下获得创建。随后处理了这一背景。此时,_item有一个EntityState.Unchanged。我对它进行了一些更改,并更改为EntityState.Modified。 (我没有想到,因为上下文(及其ObjectStateManager)应该已经消失。)无论如何,一旦它到达Save(上),它的状态(由调试器报告)就会被修改,但是我有一个新的背景。如果我在此处获得所有ObjectStateEntries(已添加,已删除,已修改,未更改)的列表,则只有两个,_item不是ApplyCurrentValues报告的其中一个,但它不能被附加,因为“它是也在那里!“。也许问题在于它仍然附加到一个旧的ObjectStateManager(可能有一些引用不会让ObjectStateManager处置?)。

+0

你在调用context.SaveChanges()两次吗? –

+0

@DannyVarod - 我正在使用UnitOfWork,在处理单元时我只调用SaveChanges,并且同时处理上下文。这是一个网络应用程序,因此它的上下文生命周期非常短。 WcfService已经用完UnitOfWork来获得_item(即我提到的“获取另一个上下文”)。但是一旦我们开始保存,SaveChanges就没有机会被调用两次了。 –

+0

你确定你没有从你的依赖注入框架获得两次相同的Uow吗? –

回答

0

问题是每次db-context被初始化时,它都会从数据库和foreach行中获取行,分配一个实体键。这意味着同一行,由2个数据库上下文检索将有2个不同的实体键。实体键就像实体框架中的一个id,它被用来代替实体的ID。但是表的约束虽然保留(没有重复的主键) 希望这是有道理的。

+0

答案是有道理的,但问题是,如何通过Attach将其报告为“已存在”并将ApplyCurrentValues报告为“找不到”? –

+0

我真的不知道是什么导致第二个问题。但试着解决第一个问题,这可能与第二个问题有关。我建议(快速测试)您使用静态的dbcontext – Boomer

0

问题是,您将两个不同的用户连接到相同的组织,但是,组织对象在每种情况下都是不同的实例。

如果该组织已经在数据库中,请尝试:

  1. 无论是导航属性设置为组织设置为null,只设置OrganizationId属性。

  2. 或从数据库中加载组织实体并将其放置在导航道具中。

如果组织没有在DB:

使用相同的实例(扔一个离开,并与其他替代它)。