NHibernate:使用现有的public int字段作为记录Id

时间:2009-09-11 21:07:55

标签: c# nhibernate orm fluent-nhibernate nhibernate-mapping

我有一个现有的课程,我想按原样坚持。

class Foo
{
    public int Id;
    ...
}

我有以下ClassMap:

class FooMap : ClassMap<Foo>
{
    Id(x => x.Id);
    ...
}

构建会话工厂会导致无效的强制转换异常。如果我的实体类具有标准的“public virtual int Id {get; private set;}”属性,则我的设置有效。我有兴趣学习是否可以使用“public int Id”字段作为nhibernate Id。

修改

看起来你现在无法用FluentNHibernate做到这一点,因为它总是处理属性。这可以通过混合NHibernate xml映射来完成。 Details on the mailing list

2 个答案:

答案 0 :(得分:2)

如果指定不应使用类级别的延迟加载(即,NHibernate不应为对象创建代理),则不必将所有属性设置为虚拟。

默认情况下,NHibernate在从数据库中检索实体实例时会创建代理。也就是说,它返回一个'空'对象,只为其填充了Id字段。 仅当您需要该对象的任何其他属性时,才会检索该对象本身。

如果您不想要此行为,可以通过在类级别指定“lazy = false”将其关闭。 使用hbm - 映射文件,您可以这样做:

<class name="MyClass" table="sometable" lazy="false">
</class>

但是,我不知道如何在Fluent中这样做;我还没有流利地玩过。

编辑: 无论如何,NHibernate必须有办法设置字段。为此,您有两个选择:

  • 第一个选项是您已经通过提供私人设定者而提供的解决方案
  • 第二个选项不是使用自动属性,而是像这样创建你的属性:

    public class MyClass
    {
    
        private int _id;
    
        public int Id { get { return _id; } }
    }
    

    然后,在映射中,您必须定义NHibernate在设置其值时应使用支持字段而不是属性。 在一个hbm映射文件中,你这样做:

    <property name="Id" column="columnname" access="field.camelcase-underscore" />
    

    正如您所看到的,您指定NHibernate应该使用该字段,并且它可以通过应用给定的命名策略来查找字段。 (在这种情况下,该字段与属性具有相同的名称,但它以下划线为前缀,并使用camelcase(第一个字符为小写)编写。 (对于身份,它应该也有效:

    <id name="Id" column="..." access="field.camelcase-underscore" />
        <generator ... />
    </id>
    

为了映射字段而不是属性,您只需要定义

access="field"

在映射文件中。但同样,我不知道如何使用Fluent ...猜猜我迫不及待地想看看Fluent。

修改 好的,我已经下载了Fluent。 :) 是不是可以这样做:

public class FooMap : ClassMap<Foo>
{
    public FooMap()
    {
        Id( x => x.Id).Access.Field ();
    }
}

答案 1 :(得分:1)

我也在邮件列表上回答了这个问题(它是cross posted there),但我认为在这里澄清也是有用的。

不幸的是,Fluent NHibernate目前假设您传递的是一个引用属性的lambda表达式(这种假设表现为对PropertyInfo类型的严重依赖)。因此,如果Id是字段而不是属性,则此行将在运行时失败:

Id( x => x.Id).Access.Field();

我们打算通过消除对PropertyInfo的依赖来最终解决这个问题。