代码之家  ›  专栏  ›  技术社区  ›  anthony

nhibernate:使用现有的public int字段作为记录ID

  •  0
  • anthony  · 技术社区  · 15 年前

    我有一个现有的类,我想保持原样。

    class Foo
    {
        public int Id;
        ...
    }
    

    我有以下类图:

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

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

    编辑

    看起来您目前无法使用FluentHibernate执行此操作,因为处理属性时总是例外。这可以通过混合使用NHibernate XML映射来实现。 Details on the mailing list .

    2 回复  |  直到 15 年前
        1
  •  1
  •   Paul Batum    15 年前

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

    不幸的是,fluent nhibernate当前假定您正在向它传递一个lambda表达式,该表达式引用一个属性(此假设由对propertyinfo类型的严重依赖来表示)。因此,如果id是字段而不是属性,则此行在运行时将失败:

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

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

        2
  •  2
  •   Frederik Gheysels    15 年前

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

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

    如果不希望出现这种行为,可以通过在类级别指定“lazy=false”来关闭它。 对于HBM映射文件,您可以这样做:

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

    但是,我不知道如何用流利的语言来演奏;我还没有用流利的语言来演奏。

    编辑: 无论如何,NHibernate必须有一种方法来设置场。为此,您有两个选项:

    • 第一个选项是通过提供一个私有setter提供的解决方案
    • 第二个选项是不要使用自动属性,并创建这样的属性:

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

      然后,在映射中,必须定义nHibernate在设置其值时应使用backing字段而不是属性。 在HBM映射文件中,您可以这样做:

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

      如您所见,您指定nhibernate应该使用该字段,并且它可以通过应用给定的命名策略来查找该字段。(在本例中,字段与属性具有相同的名称,但它的前缀是下划线,并以camelcase(第一个字符是小写)编写。 (对于一个身份,它也应该起作用:

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

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

    access="field"
    

    在映射文件中。但是,我又不知道如何用流利的语言来表达…我想我迫切需要看一下流利。

    编辑: 好的,我已经下载了流利的。:) 难道不可能这样做吗:

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

    是吗?