InvalidOperationException Entity.SaveChanges()。更新ObjectContext时出错

时间:2014-02-24 15:28:35

标签: vb.net entity-framework

我正在从源数据库中检索实体框架对象,然后将其序列化为字符串,因此我可以将其传输到其他地方。然后,我想将其反序列化并将其保存到单独的数据库中。

我正在更改对象状态的原因是因为当对象被序列化时,它已经被保存到源数据库(所以我试图欺骗EF将它们保存到新数据库中)。

有问题的对象有孩子。

Using myNewDbContext = New MyEntities() ' This is using connection for new server I'm copying open too

    myNewDbContext.ContextOptions.LazyLoadingEnabled = False
    myNewDbContext.ContextOptions.ProxyCreationEnabled = False

    myNewDbContext.Attach(myObject)
    myNewDbContext.ObjectStateManager.ChangeObjectState(myObject, System.Data.EntityState.Added)

    For Each someChild In myObject.SomeChilds
        myNewDbContext.ObjectStateManager.ChangeObjectState(someChild, System.Data.EntityState.Added)
        For Each someChildChildren In someChild.MoreChildren
            myNewDbContext.ObjectStateManager.ChangeObjectState(someChildChildren, System.Data.EntityState.Added)
        Next

    Next

    myNewDbContext.SaveChanges()

End Using

当我调用SaveChanges()时,我的对象和子节点正在保存到其他数据库,但抛出异常。我得到了InvalidOperationException

  

已成功提交对数据库的更改,但更新对象上下文时发生错误。 ObjectContext可能处于不一致状态。内部异常消息:发生了引用完整性约束违规:定义引用约束的属性值在关系中的主体和从属对象之间不一致。

关于如何阻止此错误抛出的任何想法?我可以捕获并忽略错误并且代码可以工作,但显然它会花费更长时间,因为它必须抛出异常。

实体框架=第5版 使用.NET Framework 4.0的VB.NET

2 个答案:

答案 0 :(得分:1)

我通过创建帮助函数来解决这个问题,不好意思是混合和匹配c#和vb.net(但我们的解决方案是混合的,大多数新代码都是c#)。

Using myNewDbContext = New MyEntities() ' This is using connection for new server I'm copying open too

    myNewDbContext.ContextOptions.LazyLoadingEnabled = False
    myNewDbContext.ContextOptions.ProxyCreationEnabled = False

    myNewDbContext.Attach(myObject)
    myNewDbContext.ObjectStateManager.ChangeObjectState(myObject, System.Data.EntityState.Added)
    EntityFrameworkHelper.SetEntireGraphToAdded(myObject, myNewDbContext, "myObjectType")

    myNewDbContext.SaveChanges()
End Using

public static void SetEntireGraphToAdded(EntityObject entity, ObjectContext context, string name)
{
    var i = 0;
    foreach (PropertyInfo pi in entity.GetType().GetProperties())
    {
        if ((pi.PropertyType.IsGenericType &&
                pi.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>)))
        {
            Console.WriteLine("Doing Collection {0}", pi.Name);
            var collection = (IEnumerable)pi.GetValue(entity, null);

            foreach (var val in collection)
            {
                SetEntireGraphToAdded((EntityObject)val, context, pi.Name);
            }

        }
    }

    var state = context.ObjectStateManager.GetObjectStateEntry(entity);
    state.ChangeState(EntityState.Added);

}

答案 1 :(得分:0)

这可以通过比现在做得少得多来解决:

myNewDbContext.ContextOptions.LazyLoadingEnabled = False
myNewDbContext.ContextOptions.ProxyCreationEnabled = False

myNewDbContext.ObjectStateManager.ChangeObjectState(myObject, EntityState.Added)
myNewDbContext.SaveChanges()

当您将实体的状态从Detached更改为Added时,实体所包含的整个对象图将标记为Added。在代码中,首先附加对象,然后更改状态。现在只有对象本身是Added,而不是附着的对象图。这可能就是你之后有这些循环的原因。

我认为在这些循环之后,图中仍然有Detached个对象。在执行SaveChanges时,EF将尝试执行关系修正。这是遇到与新保存的对象关联的对象,但是使用源数据库中的外键值,它会报告约束异常。

所以,Add分离的对象,并确保必须添加其对象图中的每个对象。