模型中的子节点为空,使用References<>保存时为空

本文关键字:保存 References 子节点 模型 使用 | 更新日期: 2023-09-27 18:02:27

我有一个像这样声明的对象

public class MyObject
{
    public virtual long MyId { get; set; }
    public virtual MyChild Child { get; set; }
    public MyObject()
    {
        Child = new MyChild();
    }
}
public class MyChild
{
    public virtual long MyId { get; set; }
}

我将子对象设置为"空对象",因为我想要一个空对象而不是模型中的null。

在我的数据库中,我有一个这样的表

CREATE TABLE MyObjects
(
    MyObjectId    bigint    IDENTITY(1,1) NOT NULL,
    ChildId       bigint    NULL
)

然后在我的映射中有

References<MyChild>(x => x.Child, "ChildId");

这就是问题所在。当我尝试创建一个新的MyObject时,我会得到一个错误对象引用了一个未保存的瞬态实例。所以,我这样做:

var newObject = new MyObject()
{
    Child = null
};
repository.Save(newObject);

这可以保存,但现在我的对象有一个空子,这不是我想要的行为。我可以使用的hack是在创建新的MyObject后将子节点重置为空,但我想看看是否有更好的方法。

Child需要在my object中不为空,但如果子对象的ID为0,则保存为空。

编辑

我只是测试了整个null/reset策略,它不起作用。对模型中任何对象的后续非hibernate请求都会导致暂态对象错误。

模型中的子节点为空,使用References<>保存时为空

对于正常使用和持久使用,您希望具有不同的行为。您可以实现自己的实体持久化,但这将需要大量的工作。在这种情况下,我更喜欢变通方法,因为这违反了NHibernate的假设。

public class MyObject
{
    public virtual long MyId { get; set; }
    public virtual MyChild Child { get; set; }
    protected /*internal*/ virtual MyChild ChildForPersisting
    {
        get { return (MyChild.Id == 0) ? null : Child; }
        set { if (value != null) Child = value; }
    }
    public MyObject()
    {
        Child = new MyChild();
    }
}
// with internal
References(x => x.ChildForPersisting, "ChildId")
// without internal
References(Reveal.Member<MyChild>("ChildForPersisting"), "ChildId")

另一个选项是在save eventlistener之前和之后实现它为空/重置子对象,但仍然需要很多努力。