我想在我的域中使用Null对象模式,但我不希望在我的数据库中有与之相关的记录 - 如果NHibernate能够将SQL null值映射到我的Null对象,反之亦然。
这是否可行(使用Fluent NHibernate进行映射)
P.S。这似乎是人们希望解决的一个相当普遍的问题,但我想知道为什么我一直在努力寻找答案。
修改 从这篇博客文章来看,它看起来不像是直接可能的:NHibernate & Null Object Pattern: The Options
答案 0 :(得分:1)
在不流畅的nhibernate中,您可以使用不会像这样持久存储到数据库的导入映射;
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyProject.MiddleTier"
assembly="MyProject.MiddleTier">
<import class="ThingNotToPersist"/>
</hibernate-mapping>
不知道这项工作如何流利,但希望它能为你提供一个启动。
答案 1 :(得分:0)
答案是......你做不到。 Oren说“NHibernate的null概念不是你可以轻易改变的东西,而且它不会通过拦截器这样做。你可以使用null对象作为值类型(使用UserType),但不是实体。“
答案 2 :(得分:0)
好的,自从这个问题发布以来,NHibernate 3已经发布了 - 也许现在可能有所作为了吗?
我不愿意放弃这一点 - 我想使用空对象模式,我不会对“你不能”感到满意,所以让我们考虑实现这个目标的方法! / p>
我在网上的几个帖子和笔记中遇到的一个想法是使用两个属性 - 一个具有公共(未映射)和一个具有私有(映射)访问 - 因此公共属性的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;
}
}
简而言之,在加载时用null-object替换null;在保存之前,用实际的空值替换null-object,并在保存之后,替换回null对象。
使用查询API时,您当然需要查询实际的空值,但如果您在查询API上有某种条件构建器或工厂类,则可以在那里考虑。
将您的类型扩展为专用的空对象类型,并使其成为非持久性类型。不知。强>
只是一个想法 - 假设您要将类型扩展为专用的null-object-type。有点像:
class Bar
{
public static NullBar; // instace of NullBar
}
class NullBar : Bar
{
// ...
}
既然NullBar是一个专用类型扩展Bar,我们能不能告诉NHibernate不要映射Nullar类型,即使它扩展了Bar,它被映射了?
这些是我的想法 - 其中任何一个听起来都合理吗?
(我是一个NHibernate noob,顺便说一句 - 但我坚持不懈,而不是因为你可以救我并将我放在一边等待。)