发生了参照完整性约束违规

时间:2013-04-21 06:49:50

标签: c# asp.net-mvc entity-framework-4

我正在尝试更新现有实体。

我有以下代码:

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方法抛出异常:

  

发生了引用完整性约束违规:定义引用约束的属性值在关系中的主体和从属对象之间不一致。

我该如何解决这个问题?

6 个答案:

答案 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)

让我们说您具有以下架构: schema

如果要在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