NHibernate: использование существующего публичного поля int в качестве идентификатора записи - PullRequest
0 голосов
/ 12 сентября 2009

У меня есть существующий класс, который я хотел бы сохранить как есть.

class Foo
{
    public int Id;
    ...
}

У меня есть следующая карта классов:

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

Создание фабрики сеансов приводит к недопустимому исключению приведения. Моя установка работает, если у моего класса сущности есть стандартное свойство public virtual int Id {get; private set;}. Мне интересно узнать, могу ли я использовать поле public int Id в качестве идентификатора nhibernate.

Редактировать

Похоже, в настоящее время вы не можете сделать это с FluentNHibernate, потому что он всегда исключает работу со свойствами. Это может быть достигнуто путем смешивания в сопоставлении NHibernate xml. Подробности в списке рассылки .

Ответы [ 2 ]

2 голосов
/ 12 сентября 2009

Если вы указываете, что ленивая загрузка на уровне класса не должна использоваться (то есть NHibernate не должен создавать прокси для ваших объектов), то вам не нужно делать все ваши свойства виртуальными.

По умолчанию NHibernate создает прокси при получении экземпляра вашей сущности из БД. То есть он возвращает «пустой» объект, для которого заполнено только поле Id. Только когда вам нужно какое-либо другое свойство этого объекта, сам объект извлекается.

Если вам не нужно это поведение, вы можете отключить его, указав 'lazy = false' на уровне класса. С файлом отображения hbm вы делаете это так:

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

Но я не знаю, как это сделать на беглом языке; Я еще не играл с беглым.

редактирование: В любом случае, NHibernate должен иметь способ установить поле. Для этого у вас есть 2 варианта:

  • Первый вариант - это решение, которое вы уже предоставили, предоставив частный сеттер
  • Второй вариант - не использовать автоматические свойства, а создать свою собственность следующим образом:

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

    Затем в вашем отображении вы должны определить, что NHibernate должен использовать поле поддержки вместо свойства при установке его значения. В файле отображения hbm вы делаете это так:

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

    Как видите, вы указываете, что NHibernate должен использовать это поле и что он может найти поле, применяя данную стратегию именования. (В этом случае поле имеет то же имя, что и свойство, но перед ним стоит знак подчеркивания, и оно написано в регистре верблюдов (первый символ в нижнем регистре). (Для удостоверения личности это также должно работать:

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

Чтобы отобразить поля вместо свойств, вам просто нужно определить

access="field"

в файле сопоставления. Но опять же, я не знаю, как это сделать с помощью Fluent ... Думаю, мне срочно нужно взглянуть на Fluent.

редактирование: Хорошо, я скачал свободно. :) Разве нельзя сделать это так:

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

1 голос
/ 13 сентября 2009

Я также ответил на этот вопрос в списке рассылки (там было кросс-пост ), но я подумал, что было бы полезно уточнить и здесь.

К сожалению, в настоящее время Fluent NHibernate предполагает, что вы передаете ему лямбда-выражение, которое ссылается на свойство (это предположение проявляется в сильной зависимости от типа PropertyInfo). В результате этого строка не будет работать во время выполнения, если Id - это поле, а не свойство:

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

Мы намерены в конечном итоге решить эту проблему, устранив нашу зависимость от PropertyInfo.

...