关系处于已删除状态

时间:2013-07-25 06:34:41

标签: c# entity-framework ef-code-first entity-framework-5

当我试图清除一个集合(调用.Clear)时,我得到以下异常:

  

保存不公开其关系的外键属性的实体时发生错误。 EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅InnerException。

内部例外是:

  

来自'User_Availability'AssociationSet的关系处于'已删除'状态。给定多重约束,相应的'User_Availability_Target'也必须处于'已删除'状态。

用户看起来像这样:

....
ICollection<Availability> Availability { get; set; }

可用性如下所示:

int ID { get; set; }
User User { get; set; }
DateTime Start { get; set;
DateTime End { get; set; }

配置如下:

HasMany(x => x.Availability).WithRequired(x => x.User);
HasRequired(x => x.User).WithMany(x => x.Availability);

导致问题的代码是:

user.Availability.Clear();

我已经看过其他替代方法,例如使用DbSet删除项目,但我觉得我的代码不会那么干净。有没有办法通过清除集合来实现这一目标?

3 个答案:

答案 0 :(得分:30)

我知道让它发挥作用的唯一方法是将关系定义为identifying relationship。它需要将AvailabilityUser的外键作为外键引入到您的模型中...

public int ID { get; set; }
public int UserID { get; set; }
public User User { get; set; }

...并将其作为主键的一部分:

modelBuilder.Entity<Availability>()
    .HasKey(a => new { a.ID, a.UserID });

您可以扩展映射以包含此外键(只是为了显式,不需要它,因为EF会按惯例识别它):

modelBuilder.Entity<Availability>()
    .HasRequired(a => a.User)
    .WithMany(u => u.Availability)
    .HasForeignKey(a => a.UserID);

(顺便说一句:您只需要从一方配置关系。在您的问题中不需要同时使用这两种映射。)

现在您可以使用user.Availability.Clear();清除该集合,并且将从数据库中删除Availability个实体。

答案 1 :(得分:0)

有一招。您可以在不使用特殊DbSet的情况下删除实体:

(this.dataContext as IObjectContextAdapter).ObjectContext.DeleteObject(entity);

在清除之前,对可用性集合中的每个项执行此操作。您不需要以这种方式“识别关系”。

答案 2 :(得分:0)

如果有人使用SQLite遇到相同的问题:

不幸的是,由于SQLite不支持复合键的自动递增,因此可接受的答案不适用于SQLite。

您还可以在数据库上下文中重写SaveChanges()方法以删除子级:

//// Long Version
//var localChilds = this.SubCategories.Local.ToList();
//var deletedChilds = localChilds.Where(w => w.Category == null).ToList();
//foreach(var child in deletedChilds) {
//   this.SubCategories.Remove(child);
//}

// Short in LINQ
this.SubCategories.Local
    .Where(w => w.Category == null).ToList()
    .ForEach(fe => this.SubCategories.Remove(fe));
#endregion

请参阅this很棒的Blogpost作为我的消息来源(不幸的是用德语编写)。