NHibernate中的空值对象

10
我有一个人实体,其中包含一个地址作为值对象:
public Person()
{
    WithTable("Person");
    Id(x => x.Id);
    Component<Address>(x => x.Address, a =>
    {
        a.Map(x => x.Address1);
        a.Map(x => x.Address2);
        a.Map(x => x.Address3);
        a.Map(x => x.Town);
        a.Map(x => x.Postcode);
    });
}

在 NHibernate 文档中提到,如果值对象(如 Address1、Address2 等)的所有属性都为 null,则整个组件将映射为 null(即 Person.Address 将为 null)。在所有地址字段都为 null 的情况下,这会给我带来问题,因为我可能有这样的页面(我正在使用 ASP MVC):

<%= Html.TextBoxFor((x => x.Address.Address1))%>

如果我从数据库加载Person时,所有字段都为空,那么这会导致空引用异常。因此,我正在寻找一种干净的方法,可以将Address设置为新的Address()对象,而不是null。我已经排除了以下想法:

在我的视图中进行null检查(呸,可怕)

使数据库字段不可为空(我正在处理一个旧数据库)

有人有什么想法吗?

3个回答

5

感谢James的想法(请参阅他的答案和评论),我已经修改了Person实体的Address属性,从原来的:

public virtual string Address { get; set; }

to:

private Address _address;
public virtual Address Address
{
    get { return _address ?? new Address(); }
    set { _address = value; }
}

这解决了我的问题,它有效,并且似乎可以与NHibernate一起使用。耶!


2

我没有确切的答案来创建一个未映射的方法/属性访问器,并且如果实际地址为空,则返回默认值/空对象。

public Address GetAddressOrDefault()
{
  return Address ?? new NullAddress();
}

或者类似于第一个方法,为在视图中使用的Address创建一个包装器。

public class AddressViewData
{
  private Address address;

  public AddressViewData(Address address)
  {
    this.address = address ?? new NullAddress();
  }

  // expose all address properties as pass-throughs
  public string Street
  {
    get { return address.Street; }
  }
}

当你需要在用户界面中编辑地址而不仅仅是显示它时,情况就变得相当丑陋了,是吧? - alex
有更好的建议吗? - James Gregory
太棒了,谢谢!将实际映射的Address属性访问器进行修改,以允许像往常一样进行get和set操作,但在get中使用您的null检查 "Address ?? new Address();" 即可。现在,即使地址为null,我也可以加载和编辑地址,而无需修改我的视图,同时hibernate也不会混淆。 - James Allen

0
在某些情况下,编写NHibernate自定义类型非常容易。它不是将组件设置为null,而是返回null对象。我在某些情况下这样做,这样你就可以忘记null了。 复合用户类型示例

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接