我正在尝试更新现有实体。
我有以下代码:
public MamConfiguration_V1 Save(MamConfiguration_V1 item)
{
mMaMDBEntities.MamConfiguration_V1.Attach(item);
mMaMDBEntities.ObjectStateManager.ChangeObjectState(item, System.Data.EntityState.Modified);
mMaMDBEntities.SaveChanges();
return item;
}
但Attach
方法抛出异常:
发生了引用完整性约束违规:定义引用约束的属性值在关系中的主体和从属对象之间不一致。
我该如何解决这个问题?
答案 0 :(得分:8)
似乎您与item
中的外键字段和导航属性有某种关系,并且这些字段具有冲突的值。当您加载实体及其相关实体,在一端更改关系,仅将该端标记为Modified
并尝试保存时,会发生这种情况。确保在调用Modified
之前修改两端的关系并将所有受影响的实体标记为SaveChanges
。
答案 1 :(得分:4)
项目对象的定义是什么?似乎在它的一些集合中设置与其他实体的关系存在某种类型的冲突。您可以尝试清除所有集合以查看问题是否仍然存在,但在这种情况下您丢失了外键分配。但也许它可以帮助您找到问题。
这可能是一个提示。当我尝试将现有实体附加到上下文时,我会使用以下内容:
mMaMDBEntities.Entry<MamConfiguration>(item).State = System.Data.EntityState.Modified;
您可以添加System.Data的使用,以避免一直写入它。
这会将实体附加到您想要的状态,在这种情况下进行修改并跟踪更改。这是一行而不是两行。
答案 2 :(得分:4)
我在不同情况下遇到此异常,并且在此处发布,因为在搜索错误消息时会出现此问题。
使用部分加载的实体调用IObjectContextAdapter.ObjectContext.AttachTo(entitySetName, entity)
时抛出了异常。定义了实体上的外键,但未加载导航属性。 (也就是说,O.ItemID
有一个值,但O.Item
为空。具体情况不允许加载O.Item
。
问题原来是对象状态管理器已经在一个单独的方法中加载了对象,并且已经跟踪了使用相同键定义的对象。由于单独的方法不需要跟踪对象状态,因此通过在该方法中调用IQueryable.AsNoTracking()
来解决该问题。
答案 3 :(得分:3)
我的问题是实体框架已将对象加载到多个位置,因此当我更新外键时,现在有两个对同一对象的引用,一个外键指向记录a,另一个指向指向记录b的外键,由于我的关系是一对一的,因此导致错误。为了解决它,我使用了context.Entry(Object).State = EntityState.Detached,重新加载了对象,更改了外键然后保存了我的更改
答案 4 :(得分:0)
如果要在Person中编辑CurrentLocationId,还需要编辑嵌入在Person对象中的CurrentLocation对象。 EF将自动填充CurrentLocation对象,因为CurrentLocationId在CurrentLocation的表中具有外键。当您编辑CurrentLocationId而不同时更新CurrentLocation对象时,它们将变得不同步。这就是在这种情况下导致异常的原因。
因此,假设您需要更新Person对象的CurrentLocationId。我们假设您已经预提取了Person数据和Location数据。
public class DbData
{
List<Person> PersonList;
List<Location> LocationList;
public DbData()
{
using (var context = new MyContext())
{
PersonList = context.Persons.ToList();
LocationList = context.Locations.ToList();
}
}
public void UpdatePersonLocation(Person person, int newLocationId)
{
using (var context = new MyContext())
{
var location = LocationList.Where(l=>l.id==newLocationId).Single();
//you need to update both the id and the location for this to not throw the exception
person.CurrentLocationId == newLocationId;
person.CurrentLocation == location;
context.Entry(person).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
}
//or if you're giving it the location object...
public void UpdatePersonLocation(Person person, Location location)
{
using (var context = new MyContext())
{
//you need to update both the id and the location for this to not throw the exception
person.CurrentLocationId == location.id;
person.CurrentLocation == location;
context.Entry(person).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
}
}
}
答案 5 :(得分:0)
这可能是旧文章,但以下内容对我有用
将SaveOptions option
设置为SaveOptions.DetectChangesBeforeSave