实体框架 4.1 Codefirst:“给定多重性约束”删除一对多子项时出错
我在Entity Framework 4.1中有以下类(这些类已被修剪以保持代码可读)
public class MetaInformation
{
public int Id { get; set; }
public virtual MetaInformationObject RelatedTo { get; set; }
}
public abstract class MetaInformationObject
{
public int Id { get; set; }
public virtual List<MetaInformation> MetaInformations { get; set; }
}
[Table("Hardwares")]
public class Hardware : MetaInformationObject
{
[MaxLength(100)]
public string Name { get; set; }
}
public class Inventory
{
public int Id { get; set; }
public virtual List<Machine> Machines { get; set; }
}
public class Machine : Hardware
{
public Inventory Inventory { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Isis.Business.Base.MetaInformationObject>()
.HasMany<Isis.Business.Base.MetaInformation>(mi => mi.MetaInformations).WithRequired(mi => mi.RelatedTo).WillCascadeOnDelete(true);
modelBuilder.Entity<Isis.Business.Inventory.Inventory>()
.HasMany<Isis.Business.Inventory.Machine>(i => i.Machines).WithRequired(m => m.Inventory).WillCascadeOnDelete(true);
base.OnModelCreating(modelBuilder);
}
在某一时刻,我想更新机器信息,所以如果它已经存在于数据库中,我加载它,附加它,然后清除以前的元信息以用新的元信息替换它们。
public void UpdateMachine(Inventory i, Machine m)
{
DataContext.Dao.Db.Inventories.Attach(i);
if (!i.Machines.Exists(InnerHardware => InnerHardware.SerialNumber == m.SerialNumber)) {
i.Machines.Add(m);
} else {
var workingMachine = i.Machines.First(Machine => Machine.SerialNumber == m.SerialNumber);
Dao.Db.Machines.Attach(workingMachine);
if (workingMachine.MetaInformations != null && workingMachine.MetaInformations.Count > 0) {
workingMachine.MetaInformations.Clear();
//workingMachine.MetaInformations.ForEach(mi => { Dao.Db.MetaInformations.Attach(mi); Dao.Db.MetaInformations.Remove(mi); }); // tried this to, with variations
}
workingMachine.MetaInformations = m.MetaInformations;
}
DataContext.Dao.Db.SaveChanges();
}
然后,抛出以下 DbUpdateException:
来自“MetaInformationObject_MetaInformations”的关系 AssociationSet 处于“已删除”状态。给定多重性 约束,相应的 “MetaInformationObject_MetaInformations_Target”也必须在 “已删除”状态。
我尝试在这里遵循一些问题来解决问题,特别是尝试阅读 这个 和 答案中提供的链接(这就是为什么从 MetaInformation
直接引用 MetaInformationObject
的原因),但我不知道出了什么问题。
I have the following classes in Entity Framework 4.1 (the classes have been pruned to keep the code readable)
public class MetaInformation
{
public int Id { get; set; }
public virtual MetaInformationObject RelatedTo { get; set; }
}
public abstract class MetaInformationObject
{
public int Id { get; set; }
public virtual List<MetaInformation> MetaInformations { get; set; }
}
[Table("Hardwares")]
public class Hardware : MetaInformationObject
{
[MaxLength(100)]
public string Name { get; set; }
}
public class Inventory
{
public int Id { get; set; }
public virtual List<Machine> Machines { get; set; }
}
public class Machine : Hardware
{
public Inventory Inventory { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Isis.Business.Base.MetaInformationObject>()
.HasMany<Isis.Business.Base.MetaInformation>(mi => mi.MetaInformations).WithRequired(mi => mi.RelatedTo).WillCascadeOnDelete(true);
modelBuilder.Entity<Isis.Business.Inventory.Inventory>()
.HasMany<Isis.Business.Inventory.Machine>(i => i.Machines).WithRequired(m => m.Inventory).WillCascadeOnDelete(true);
base.OnModelCreating(modelBuilder);
}
At one point, i'd like to update a machine information, so if it already exists in the database, i load it, attach it and then clear the previous metainformations to replace them with the new ones.
public void UpdateMachine(Inventory i, Machine m)
{
DataContext.Dao.Db.Inventories.Attach(i);
if (!i.Machines.Exists(InnerHardware => InnerHardware.SerialNumber == m.SerialNumber)) {
i.Machines.Add(m);
} else {
var workingMachine = i.Machines.First(Machine => Machine.SerialNumber == m.SerialNumber);
Dao.Db.Machines.Attach(workingMachine);
if (workingMachine.MetaInformations != null && workingMachine.MetaInformations.Count > 0) {
workingMachine.MetaInformations.Clear();
//workingMachine.MetaInformations.ForEach(mi => { Dao.Db.MetaInformations.Attach(mi); Dao.Db.MetaInformations.Remove(mi); }); // tried this to, with variations
}
workingMachine.MetaInformations = m.MetaInformations;
}
DataContext.Dao.Db.SaveChanges();
}
And then, the following DbUpdateException is thrown:
A relationship from the 'MetaInformationObject_MetaInformations'
AssociationSet is in the 'Deleted' state. Given multiplicity
constraints, a corresponding
'MetaInformationObject_MetaInformations_Target' must also in the
'Deleted' state.
I tried following some questions here on SO to solve the problem, especially trying to read this one and the link provided in the answer (that's the reason why there's a direct reference from MetaInformation
to MetaInformationObject
) but i can't figure out what's wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
级联删除在这里对你没有帮助。仅当您删除父实体 (
MetaInformationObject
) 时,级联删除才有效。这里的问题是,对相关对象的集合调用 Clear 不会删除它们。它仅删除关系(= 它将把MetaInformation
中的外键设置为 null),但您的映射约束不允许这样做(您根据需要定义了关系)。避免这种情况的方法是:Clear
不仅会破坏关系,还会将相关实体标记为已删除。Cascade delete will not help you here. Cascade delete works only if you delete parent entity (
MetaInformationObject
). The problem here is that calling Clear on the collection of related objects doesn't delete them. It only deletes the relation (= it will set foreign key inMetaInformation
to null) but it is not allowed by your mapping constraints (you defined relation as required). The ways to avoid this are either:MetaInformation
s and delete each of themClear
will not only break the relation but mark related entity as deleted as well.呼应上面的评论,下面的代码可以解决您的问题
DataContext.Dao.Db.MetaInformations.RemoveRange(workingMachine.MetaInformations);
Echoing above comment, below code would solve your problem
DataContext.Dao.Db.MetaInformations.RemoveRange(workingMachine.MetaInformations);