我正在尝试创建一个父对象,该对象在1对多关系中有多个子对象。我没有在子对象上引用Parent对象,而是将其keycolumn映射为字段。
当我第一次尝试保存此对象时,它按预期工作,没有任何问题(级联所有Id和子级)。当我尝试从数据库中获取对象时,更新它上面的一些属性并重新保存它,它会失败。我得到的实际错误消息是“无法删除集合”。
上面的错误是由于它试图将子对象上的“ParentId”字段设置为NULL(这违反了我在db中的FK约束)。如果我从数据库中删除此约束,最终结果就是我想要的;但是,我不希望它执行此更新(将父ID设置为null)并且我不确定它为什么。从我在SQL代码中可以看出它生成并发送到数据库,其他一切看起来都是正确的,如果它不适用于最后一个更新语句,它将全部工作。
显然,我的映射确实有问题,但我无法弄清楚是什么。我尝试添加Not.KeyUpdate(),但这简直使它根本不生成密钥。有没有人有任何想法我做错了什么?
先谢谢,我真的很感激!!!
请参阅下面的我的地图:
public class Parent
{
public Parent()
{
Children = new List<Child>();
}
public virtual Guid Id { get; set; }
public virtual IList<Child> Children { get; set; }
}
public class Child
{
public virtual Guid Id { get; set; }
public virtual Guid ParentId { get; set; }
}
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Table("Parent");
Id(x => x.Id);
HasMany(x => x.Children).KeyColumn("ParentId").Cascade.SaveUpdate().Not.LazyLoad();
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Table("Child");
Id(x => x.Id);
Map(x => x.ParentId);
}
}
答案 0 :(得分:1)
这是因为 children 的集合未标记为inverse="true"
。
您可以做的是:I。从DB中删除约束。 NHiberante只需要(没有反向设置)做2个步骤。首先更新记录以打破关系,其次(由于级联)删除项目
II。更改映射和实体。像这样:
Child
必须引用Parent
:
public class Child
{
public virtual Guid Id { get; set; }
public virtual Guid ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
然后映射将是这样的:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
Table("Parent");
Id(x => x.Id);
HasMany(x => x.Children)
.KeyColumn("ParentId")
.Cascade.SaveUpdate()
.Not.LazyLoad()
.Inverse() // here we do have the inverse setting
;
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
Table("Child");
Id(x => x.Id);
Map(x => x.ParentId).Not.Insert().Not.Update(); // this is readonly now
References(x => x.Parent).Column("ParentId"); // just a Parent is writable
}
}
现在,您必须始终在C#代码中正确设置关系。即如果将child添加到Parents集合中,则还应设置Parent引用
parent.Children.Add(child);
child.Parent = parent;
NHibernate现在只发出一个语句,从表中删除子项