2010-11-05 53 views
5

我有一个类似这样的域类。我希望NHibernate在保存当前值LastUpdate插入/更新时,以便我可以在查询中使用它,但从数据库中检索Foo时忽略它,并让对象本身重新计算实际访问它时的值。使用流利NHibernate映射一个只读属性没有设置器

public class Foo { 
    public DateTime LastUpdate { 
     get { 
      /* Complex logic to determine last update by inspecting History */ 
      return value; 
     } 
    } 
    public IEnumerable<History> History { get; set; } 
    /* etc. */ 
} 

我对Foo映射是这样的:

public class FooMap : ClassMap<Foo> { 
    Map(x => x.LastUpdate) 
     .ReadOnly(); 
    HasMany(x => x.History); 
    // etc... 
} 

我认为ReadOnly()是我想做到这一点,但是当我尝试创建一个SessionFactory我得到以下异常:

Error: FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
---> NHibernate.PropertyNotFoundException: Could not find a setter for property 'LastUpdate' in class 'Foo'.

该属性没有setter,因为它不应该设置,只能从读取。是ReadOnly()在这里做的正确的事情?如果不是,什么?

(NHibernate的v3.0b1,功能NHibernate V1.1)

+0

只读() ;仅在生成的映射xml流中设置LastUpdate属性的insert =“false”和update =“false”属性。 – tolism7 2010-11-07 00:13:58

回答

12

ReadOnly指示流利NHibernate不寻找这个属性的变化,这不等同于编译器世界中的只读属性。你的财产在NHibernate的眼中不是只读的,因为你期望它从数据库中填充。你需要做的是告诉NHibernate,它应该通过与属性名称相同(小写)的私有字段来访问该属性的值。

Map(x => x.LastUpdate) 
    .Access.Field(); 

有几个选择使用Field,你用哪一个取决于你如何命名你的私人领域。

+2

我实际上并不想从数据库中填充属性,它是在getter中动态计算的。我只是希望它被保存到数据库,以便我可以查询它。 – 2010-11-08 15:58:16

+6

如果Nhibernate没有填充它,它将不知道保存它,因为它不知道该值是否以及何时发生更改。提供的两种解决方案都完全相同,并按照您的描述进行。 NHibernate可以通过字段访问变量,所以你不需要setter。当您访问getter时,该值将被动态计算。当你更新NHibernate会保存值。 NHibernate从db中填充它的事实应该是无关紧要的 - 直到你访问你不知道/关心,当你访问它时,它的值将被计算。看看Nhibernate“初始化”是否有帮助。 – Sisyphus 2010-11-09 06:30:59

+0

@Sisyphus这个解释有很大帮助。谢谢。 – 2010-11-12 19:06:37

2

至于NHibernate的推移,可以映射到一个字段,即成员变量所以Nhibernate的可以直接访问成员变量。所以你可以创建一个像_lastUpdate这样的可以直接映射的成员变量。 Nhibernate现在将有一个变量来使用,你可以在你的getter中单独控制这个值,因为NHibernate将不再使用属性getter。它会保存值并检索它,但是检索到的值并不重要,因为只要通过getter访问,就可以重新计算它。同样没有getter或setters的私有变量。

在普通的HBM中,您只需映射access =字段即可。每个人都这样做。显然Fluent并不简单。我不使用流利......

编辑...

找到任何映射私人支持字段看似永远向前的目标是在你的版本,以...

+1

这与Fluent NHibernate一样简单:'Map(x => x.LastUpdate).Access。Field()' – 2010-11-08 15:12:37

0

只需添加一个空的私人二传手到类:

 private set { } 

我还添加属性和注释来记录我的意图(做出ReSharper的快乐):

 [UsedImplicitly] 
     // ReSharper disable once ValueParameterNotUsed 
     private set { }