【问题标题】:How can I make NHibernate aware of a first-class "Null Object", without database persistence?在没有数据库持久性的情况下,如何让 NHibernate 知道一流的“空对象”?
【发布时间】:2009-07-03 08:19:31
【问题描述】:

我想在我的域中使用 Null 对象模式,但我不想在我的数据库中有与之相关的记录 - 如果 NHibernate 能够将 SQL 空值映射到我的 Null 对象,反之亦然。

这可能吗(使用 Fluent NHibernate 进行映射)

附:这似乎是人们希望解决的一个相当普遍的问题,但我想知道为什么我一直在努力寻找答案。

编辑: 从这篇博文来看,这看起来不太可能:NHibernate & Null Object Pattern: The Options

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping null-object-pattern


    【解决方案1】:

    在不流畅的 nhibernate 中,您可以使用不会像这样持久保存到数据库的导入映射;

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
          namespace="MyProject.MiddleTier"    
          assembly="MyProject.MiddleTier">
       <import class="ThingNotToPersist"/>
    </hibernate-mapping>
    

    不知道它是如何流畅地工作的,但希望它能给你一个入门。

    【讨论】:

    • 谢谢,不过我不太确定如何将其应用于空对象模式。
    • 嗯,抱歉,我并没有真正将这种模式应用到我正在做的工作中。我将此技术与 ICriteria 一起使用,以从集合中获取最新的对象。在针对映射持久对象的查询中,我使用 Projection 来获取最新对象,然后使用 Treansformer 将我的持久对象转换为映射的非持久对象。我真的不能再详细说明了,但是我在这里得到了帮助,当我找到它时,我会发布一个链接。
    【解决方案2】:

    答案是……你不能。 Oren 说“NHibernate 的 null 概念不是您可以轻易更改的,而且它不会通过拦截器来更改。您可以将 null 对象用于值类型(使用 UserType),但不适用于实体。”

    【讨论】:

      【解决方案3】:

      好的,既然发布了这个问题,NHibernate 3 就发布了——也许现在有什么可能?

      我不愿意放手——我想使用空对象模式,而且我不会满足于“你不能”,所以让我们想办法实现这一点!

      我在网络上的几篇文章和笔记中遇到的一个想法是使用两个属性 - 一个具有公共(未映射)访问权限,一个具有私有(映射)访问权限 - 因此公共属性的 get-accessor 将像return MyPrivate ?? MyType.NullObject 这样的东西......我已经消除了这个想法,因为它会在查询界面上产生问题——你不能查询公共属性,因为它没有被映射。所以我们可以忘记这种方法。

      我有两个从未见过的想法:

      使用拦截器在读/写之前/之后更改属性值。

      有人提到拦截器不起作用,但请耐心等待......在伪代码中:

      class Foo
      {
          public Bar Bar { get; set; }
      }
      
      class Bar
      {
          public static Bar None;
      }
      
      class MyInterceptor
      {
          public void AfterLoad(IEntity object)
          {
              foreach (property in object)
                  if (property.type == typeof(Bar) && property.value == null)
                      object[property].value = Bar.None;
          }
      
          public void BeforeSave(IEntity object)
          {
              foreach (property in object)
                  if (property.type == typeof(Bar) && property.value == Bar.None)
                      object[property].value = null;
          }
      
          public void AfterSave(IEntity object)
          {
              foreach (property in object)
                  if (property.type == typeof(Bar) && property.value == null)
                      object[property].value = Bar.None;
          }
      }
      

      简而言之,在加载时用空对象替换空值;保存前,用实际的空值替换空对象,保存后,将空对象替换回去。

      当使用查询 API 时,您当然需要查询实际的空值,但如果您在查询 API 上有某种标准生成器或工厂类,则可以在那里考虑。

      将您的类型扩展为专用的空对象类型并使其非持久化。不知何故。

      只是一个想法-假设您要将类型扩展为专用的空对象类型。大致如下:

      class Bar
      {
          public static NullBar; // instace of NullBar
      }
      
      class NullBar : Bar
      {
          // ...
      }
      

      既然 NullBar 是扩展 Bar 的专用类型,我们能否以某种方式告诉 NHibernate 不要映射 Nullar 类型,即使它扩展了已映射的 Bar?

      这些是我的想法——其中任何一个听起来都合理吗?

      (顺便说一句,我是一个 NHibernate 菜鸟——但我很坚持,并不是说你可以救我,然后把我放在一边。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-16
        • 2022-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-05
        • 2014-11-10
        • 2011-01-16
        相关资源
        最近更新 更多