使用Fluent NHibernate映射没有setter的只读属性

Bra*_*bby 5 nhibernate fluent-nhibernate

我有一个看起来像这样的域类.我希望NHibernate 在插入/更新时保存当前值,LastUpdate以便我可以在查询中使用它,但是在Foo从数据库中检索a时忽略它并让对象本身在我实际访问它时重新计算该值.

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. */
}
Run Code Online (Sandbox Code Playgroud)

我的映射Foo看起来像这样:

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

我认为这ReadOnly()就是我想要实现的目标,但是当我尝试创建SessionFactory时,我得到以下异常:

错误:FluentNHibernate.Cfg.FluentConfigurationException:创建SessionFactory时使用了无效或不完整的配置.检查PotentialReasons集合,以及InnerException以获取更多详细信息.
---> NHibernate.PropertyNotFoundException:无法在类'Foo'中找到属性'LastUpdate'的setter.

该属性没有setter,因为它不应该被设置,只能从中读取.这ReadOnly()是正确的做法吗?如果不是,那是什么?

(NHibernate v3.0b1,Fluent NHibernate v1.1)

Jam*_*ory 14

ReadOnly指示Fluent NHibernate不查找此属性的更改,这不等于编译器世界中的只读属性.您的属性在NHibernate眼中不是只读的,因为您希望它从您的数据库中填充.您需要做的是告诉NHibernate它应该通过与属性具有相同名称(小写)的私有字段来访问该属性的值.

Map(x => x.LastUpdate)
  .Access.Field();
Run Code Online (Sandbox Code Playgroud)

有几种使用方法Field,您使用哪种方法取决于您如何命名私有字段.

  • 如果Nhibernate没有填充它,它将不知道保存它,因为它不知道值是否以及何时更改.提供的两种解决方案完全相同,并按照您的描述进行操作.NHibernate可以按字段访问变量,因此您不需要setter.当您访问getter时,将动态计算该值.当您更新NHibernate时将保存该值.NHibernate从数据库中填充它的事实应该是无关紧要的 - 直到你访问你不知道/关心,当你访问它时,将计算值.如果它有帮助,请看Nhibernate的"初始化". (6认同)
  • 我会使用Access.ReadOnly() (3认同)
  • 我实际上并不希望从数据库中填充属性,它是在getter中动态计算的.我只是想将它保存到数据库中,以便我可以查询它. (2认同)