我正在从源数据库中检索实体框架对象,然后将其序列化为字符串,因此我可以将其传输到其他地方。然后,我想将其反序列化并将其保存到单独的数据库中。
我正在更改对象状态的原因是因为当对象被序列化时,它已经被保存到源数据库(所以我试图欺骗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
答案 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
分离的对象,并确保必须添加其对象图中的每个对象。