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

时间:2010-11-05 21:12:58

标签: nhibernate fluent-nhibernate

我有一个类似于此的域类。我希望NHibernate在插入/更新时保存当前值LastUpdate,以便我可以在查询中使用它,但在从数据库中检索Foo时忽略它当我实际访问它时,让对象本身重新计算值。

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时,我得到以下异常:

  

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

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

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

3 个答案:

答案 0 :(得分:13)

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

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

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

答案 1 :(得分:2)

就NHibernate而言,你可以映射到一个字段,即成员变量,这样Nhibernate就可以直接访问成员变量。因此,您可以创建一个可以直接映射的成员变量,如_lastUpdate。 Nhibernate现在将使用一个变量,你可以在getter中单独控制值,因为NHibernate将不再使用属性getter。它会保存值并检索它,但检索到的值无关紧要,因为只要您通过getter访问它就可以重新计算它。同样没有getter或setter的私有变量。

在常规的hbm中,您只需映射access = field。每个人都这样做。显然,流利并不简单。我不使用Fluent ...

编辑......

找到用于映射私有支持字段的看似始终移动的目标在您的版本中并使用...

答案 2 :(得分:0)

只需在您的班级中添加一个空的私人设定器:

        private set { }

我还添加了一个属性和注释来记录我的意图(让ReSharper感到高兴):

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