NHibernate组件映射 - Null组件

时间:2009-04-21 01:44:53

标签: nhibernate fluent-nhibernate

我有一个映射实体Matter,它有一个映射组件,Injury。

伤害的唯一属性是DateOfInjury,这是一个可以为空的日期时间。

当我检索Matter时,如果DateOfInjury为null,则该组件为null。

因此就像这件事.Injury.DateOfInjury将抛出。

有人可以解释我是否做了明显的事情导致这种行为吗?

我原本预计Injury组件会被nHibernate初始化为一个对象,并且DateOfinjury属性为null。

我会想到这会更灵活吗?

5 个答案:

答案 0 :(得分:10)

我认为这是组件映射的默认行为。组件的NHibernate文档说如果组件的所有元素都为null,则组件本身将为null。

如果组件中只有一个属性,那么将它映射为Matter类上的可为空的DateTime属性可能是有意义的。

答案 1 :(得分:5)

我也遇到了同样的问题,即期望NHibernate初始化我的组件,即使它的所有成员在数据库中都是null。这个实现背后的动机是将关于我的组件的逻辑移动到组件中,而不必处理它是否为null。

感谢这篇文章我的搜索解释了为什么我的单元测试失败了组件内部的所有空值都很短。我通过扩展组件类ArrivalDay的自动属性并在分配null时自己分配一个新实例来修复这个问题:

private ArrivalDay _arrivalDay;
public ArrivalDay ArrivalDay
{
    get { return _arrivalDay; }
    set { _arrivalDay = value ?? new ArrivalDay(); }
}

这就像魅力一样,对包含类的开销很小。

答案 2 :(得分:2)

我已经通过将此属性添加到我的组件类

来解决了这个问题
public virtual bool _LoadAlways { get { return true; } set { } }

答案 3 :(得分:1)

这是一种技术上可行的解决方案。我已经用持久性测试它并没有产生瞬态相关问题。

protected internal virtual Injury NullableInjury {get;set;}
public virtual Injury Injury 
{
   get{return NullableInjury ?? (NullableInjury = new Injury()); 
}

在Nhibernate中将您的组件映射到NullableInjury。 此解决方案允许您在没有@Oliver解决方案中报告的瞬态问题的情况下持续存在。

答案 4 :(得分:0)

https://stackoverflow.com/a/11187173/206297对我不起作用,但建立在它上面:

public class Injury
{
    // ...
    private bool dummyFieldToLoadEmptyComponent { get; set; }
}

public class MatterMap : ClassMap<Matter>
{
    // ...
    Component(x => x.Injury, m =>
    {
        // ...
        m.Map(Reveal.Member<Injury>("dummyFieldToLoadEmptyComponent")).Formula("1=1").ReadOnly();
    });
}

Reveal.Member位只是为了映射Fluent NHibernate中的私有字段。我们希望该字段是私有的,因为我们不希望该属性作为组件的公共接口的一部分公开。见https://github.com/jagregory/fluent-nhibernate/wiki/Mapping-private-properties。如果你不介意公开它,你可以使用较简洁的映射:

m.Map(x => x.DummyFieldToLoadEmptyComponent).Formula("1=1").ReadOnly();

Formula部分是因为我们实际上并不想在数据库中使用列。 NHibernate将在加载组件时执行该公式,并且它将始终评估为true。我选择1 = 1,因为我认为这是合理的跨DB。

毫无疑问是一个黑客,但似乎到目前为止加载空组件并且在持久化时没有造成任何错误。但请慎重使用。