Свойство коллекции NHibernate 3.2 пусто, в то время как вспомогательное поле содержит элементы - PullRequest
4 голосов
/ 12 июля 2011

Я использую NHibernate 3.2 и у меня проблема с отображением коллекции.

После запроса учетной записи пользователя ...

UserAccount userAccount = (from u in Session.Query<UserAccount>()
                           where u.Username == username
                           select u).SingleOrDefault();

... свойство Roleсодержит пустую коллекцию, в то время как поле roles содержит актуальные элементы:

Debugger view

Это ошибка в NH 3.2 или что-то в этом роде?Я почти уверен, что он работал на 3.1.

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

EDIT 1

Чтобы помочь мне узнать, что происходит внутри прокси-сервера, я только что разместил вопрос: Есть ли способ декомпилировать прокси-классы, сгенерированные NHibernate? .Я думаю, что предмет заслуживает того, чтобы быть вопросом сам по себе, потому что он может быть полезен во многих других ситуациях.

РЕДАКТИРОВАТЬ 2

Ну, мне удалось декомпилироватьдинамический прокси-класс.Это метод, который управляет отложенной загрузкой свойства Roles:

public override IEnumerable<Role> get_Roles()
{
    IInterceptor interceptor = this.Interceptor;
    if (interceptor == null)
    {
        throw new NotImplementedException();
    }

    object[] args = new object[0];

    InvocationInfo info = new InvocationInfo(
        this, (MethodInfo)methodof(UserAccount.get_Roles),
        null, new Type[0], args);

    args = info.Arguments;
    return (IEnumerable<Role>)interceptor.Intercept(info);
}

Я не думаю, что здесь происходит что-то особенное.

РЕДАКТИРОВАТЬ 3

Во время отладки перехватчика (который частично показан ниже), я заметил, что когда он вызывается для methodName == "get_Roles", для свойства TargetInstance (в данном случае это UserAccount), этоroles поле является пустой коллекцией.Однако перед доступом к свойству Roles в экземпляре прокси поле прокси *1046* содержит заполненную коллекцию.

public class DefaultDynamicLazyFieldInterceptor
    : IFieldInterceptorAccessor, Proxy.DynamicProxy.IInterceptor
{
    ...
    public object Intercept(InvocationInfo info)
    {
        var methodName = info.TargetMethod.Name;

        if (FieldInterceptor != null)
        {
            ...

При проверке экземпляра InvocationInfoproxy и Target экземпляры do имеют поле roles, содержащее заполненную коллекцию.

РЕДАКТИРОВАТЬ 4

Я думаю,что я столкнулся с NH Выпуск 2772 - Ленивая коллекция не загружается, когда свойство загружено Лениво .

КОНЕЦ РЕДАКТИРОВАНИЯ

Вот классы сущностей:

public class UserAccount : Entity
{
    ...
    private IList<Role> roles;

    public virtual IEnumerable<Role> Roles
    {
        get
        {
            return roles;
        }
    }
    ...
}

public class Role : Entity
{
    ...
}

Вот часть файла отображения HBM для сопоставления UserAccount:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" 
                   auto-import="false" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true"
         dynamic-update="true" schema="[MySchema]" mutable="true"
         name="MyNamespace.UserAccount, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
         table="UserAccounts">
    ...
    <bag access="nosetter.camelcase" cascade="none" name="Roles"
         schema="[MySchema]" table="UserAccounts_Roles" mutable="true">
      <key>
        <column name="UserAccountId" />
      </key>
      <many-to-many class="MyNamespace.Role, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="RoleId" />
      </many-to-many>
    </bag>
    ...
  </class>
</hibernate-mapping>

А вот часть HBM, которая определяет отображение ролей:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property"
                   auto-import="false" default-cascade="none" default-lazy="true">
  <class xmlns="urn:nhibernate-mapping-2.2" dynamic-insert="true"
         dynamic-update="true" schema="[MySchema]" mutable="true"
         name="MyNamespace.Role, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
         table="Roles">
    ...
  </class>
</hibernate-mapping>

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

попробуйте использовать

bag access="field.camelcase" 

вместо

bag access="nosetter.camelcase"
0 голосов
/ 16 июля 2013

Я только что проверил проблему 2772 и, по-видимому, она была исправлена, и ее планируется выпустить в следующей основной версии NHibernate (которую планируется назвать 4.0).Поэтому я отмечаю вопрос как ответ, хотя и немного преждевременно.

...