39

嘿,我有一个带有一堆 inproc 缓存和实体框架的应用程序。当我想向实体写入更新时,我会重新附加缓存的副本。我跟踪我在上下文的生命周期中附加的所有内容,因此我不会尝试将它们附加两次。

我在附加时发生错误(在大多数情况下很少会正常工作并且非常快),它说明了以下内容:

发生参照完整性约束冲突:定义参照约束的属性值在关系中的主体对象和从属对象之间不一致。

我已经非常仔细地查看了看起来很正常的实体。我认为这个问题是由于修复运行时外键的附加/分离造成的。

是否有一种好方法可以获取有关此错误的更多信息,或者它是否会由于实体处于 EF 不期望的状态以外的原因而发生?

编辑:DB 图(注意我使用的是 codefirst,我只是使用 EDMX 工具制作图表,为简单起见,我还从模型中删除了一堆常规属性)

在此处输入图像描述

4

7 回答 7

54

Person除了多对多关系之外,Location您的模型中显然存在的一对多关系可能会发生错误。例如下面的代码会抛出异常:

using (var context = new MyContext())
{
    var person = new Person
    {
        CurrentLocationId = 1,
        CurrentLocation = new Location { Id = 2 }
    };
    context.People.Attach(person); // Exception
}

“定义引用约束的属性值”是外键属性值CurrentLocationId和主键值CurrentLocation.Id。如果这些值不同,则会引发异常。(CurrentLocation好像null是允许的。)

在我看来,只能为外键关联抛出此异常,因为只有对于这种类型的关联,您才具有在模型中定义引用约束的属性。它不能为独立协会抛出。由于每个多对多关系都是一个独立的关联(模型中没有外键属性),我的猜测是错误与您的多对多关系无关,而是与一对多相关。

于 2012-07-21T22:45:06.640 回答
10

我遇到了一个非常相似的异常:

"A referential integrity constraint violation occurred: 
The property value(s) of 'ObjectA.PropertyX' on one end of a relationship 
do not match the property value(s) of 'ObjectB.PropertyY' on the other end."

原因是这样的:Web API 的客户端发送了一个 PUT 请求,其中包含整个对象,包括导航属性(在此示例中,ObjectA(更准确地说是 ObjectB.ObjectA)是一个导航属性,完全由客户端提供)。发生这种情况是因为客户端从服务器接收到整个对象并将其按原样退回到服务器,并进行了微小的更改。

另一方面,ObjectB.PropertyY 刚刚被更改(这首先是 PUT 请求的原因)。

由于 ObjectB.PropertyY 是对同一个对象 ObjectA(外键)的引用,EF 尝试对此进行协调,但由于上述异常而失败。

解决方案很简单:

ObjectB.ObjectA = null;

在 SaveChanges() 完全解决这个问题之前。

我希望这可以帮助别人。

于 2018-01-30T08:08:56.923 回答
2

我刚刚遇到了同样的问题,我的解决方案是我已经向关联添加了映射,然后设置了引用约束。

为了解决这个问题,我必须打开关联的映射窗口,并且有一个链接可以删除映射。一旦完成映射详细信息窗口,然后说映射是不允许的.. 似乎添加引用约束会使任何映射留在原处。

认为如果其他人将来正在寻找此错误消息的解决方案,可能值得发布。

于 2014-09-19T08:29:01.623 回答
1

@LukeMcGregor 嗨,

作为有同样问题的人,我想我可以提供不同的观点。

在我执行了所有必要的检查之后,我可以说我更愿意得到这个错误。

因为在我的场景中:我想包含一个导致不匹配错误的对象。它是您场景中的位置对象。如果我添加一个带有 ID 的对象,我会收到此错误,因为前一个对象(未更新的对象)中的 ID 与更新后的 ID 不匹配。

但这不是一个大问题。作为解决方案;如果它仍然在 UI 端,如果它仍然存在,它可能仍然被包含。

当您收到用户的更新请求时,您将清空对象。(= Null)或者您将使用用户在服务端更新(附加,修改......无论如何)之前更新的ID更新对象并以这种方式更新它。

而已。它可以在数据库和图表中保持原样。

于 2017-08-28T08:49:45.083 回答
1

要添加到@Slauma 的答案,不仅仅是在将对象添加到您的上下文时。对于您的示例,如果您在 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();
        }
    }
}
于 2018-11-07T18:02:10.757 回答
0

我刚遇到这个问题并想出了一个非常快速的解决方案。我的问题是多对多表。

Public class Pictures_Tag
{
    [Key]
    [Column(Order = 0)]
    [ForeignKey("Picture")]
    public Int16 Picture_ID { get; set; }
    [Key]
    [Column(Order = 1)]
    [ForeignKey("ImageTag")]
    public Int16 ImageTag_ID { get; set; }
    public virtual Picture Picture { get; set; }
    public virtual ImageTag ImageTag { get; set; }
}

我添加了我分配的行,Picture = db.Pictures...然后它工作正常(不完全确定为什么)

[HttpPost]
public ActionResult Edit2(WebSiteEF2017C.Models.Pictures_Tag p)
{     
    using (var db = new thisModel(Session["org"].ToString())
    {
         p.Picture = db.Pictures.Where(z => z.ID == p.Picture_ID).FirstOrDefault();
         db.Pictures_Tags.Attach(p);
         db.Entry(p).State = EntityState.Modified;
         db.SaveChanges();
         return View(db.Pictures_Tags.Include(x => x.Picture)
                    .Where(n => n.Picture_ID == p.Picture_ID & n.ImageTag_ID == p.ImageTag_ID).FirstOrDefault());
    }
}
于 2018-05-30T23:28:06.303 回答
0

尝试将任何子类对象设置为 null MainObject.SubObject1 = null; 人.地址=空;// 地址对象为 null 而不是 id

于 2021-03-10T21:51:41.310 回答