Игнорирование методов на типах сущностей с помощью nHibernate - PullRequest
9 голосов
/ 13 июля 2009

У меня есть что-то вроде этого:

public class Account
{
    public virtual int Id { get; private set; }
    public virtual string Username { get; set; }

    [EditorBrowsable( EditorBrowsableState.Never )]
    public virtual string Password { get; private set; }

    public void SetPassword( string password ){ ... }
    public bool CheckPassword( string password ) { ... }
}

Я настроил это так, потому что никогда не хочу, чтобы свойство Password использовалось непосредственно в коде, который использует тип Account. Карта аккаунта выглядит примерно так:

public class AccountMap : ClassMap<Account>
{
    public AccountMap()
    {
        Id( x => x.Id );
        Map( x => x.Username );
        Map( x => x.Password );
    }
}

Когда я на самом деле использую это с NHibernate, я получаю InvalidProxyTypeException

NHibernate.InvalidProxyTypeException: The following types may not be used as proxies:
    Fringine.Users.Account: method SetPassword should be virtual
    Fringine.Users.Account: method CheckPassword should be virtual

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

Оценивает ли NHibernate (или Castle внутри) содержимое метода, чтобы определить, какие поля используются, и оптимизировать отложенную загрузку для этих свойств? Если нет, то почему метод должен быть виртуальным, если все свойства есть, и они будут загружаться лениво, когда на них ссылается метод.

Есть ли способ исключить определенные методы из виртуального требования?

Ответы [ 3 ]

7 голосов
/ 21 октября 2009

Причина в том, что вы можете получить доступ к полям в ваших методах, которые не будут инициализированы. Таким образом, самый простой способ - загрузить содержимое объекта при любом вызове объекта (единственное исключение - доступ к идентификатору, который уже доступен в прокси-сервере).

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

Если вы считаете, что это проблема для вашего класса, попробуйте перенести функциональность в другой класс (например, PasswordManager, PasswordValidator и т. Д.). Этот класс будет объединять учетную запись или принимать ее в качестве аргумента, поэтому учетная запись будет загружена только тогда, когда этот класс фактически вызовет одно из ее свойств.

0 голосов
/ 14 июля 2009

Вы можете деактивировать ленивую загрузку на уровне класса и активировать ее для свойства в зависимости от свойства; ленивая загрузка часто используется для отношений коллекции-ассоциации.

public class AccountMap : ClassMap<Account>{        
    public AccountMap()
    {
        Not.LazyLoad();
        Id( x => x.Id );
        Map( x => x.Username ).LazyLoad();
        Map( x => x.Password );        
    }
}

Или вы можете попробовать использовать закрытое поле и "полевую" стратегию для него:

public class AccountMap : ClassMap<Account>{        
    public AccountMap()
    {

        Id( x => x.Id );
        Map( x => x.Username )
        Map( x => x.Password).Access.AsCamelCaseField();         
    }
}

public class AccountMap : ClassMap<Account>{        
   private string password;
   public string Password{ get; }
}
0 голосов
/ 13 июля 2009

Я заметил, что NHibernate в значительной степени зависит от POCO для всех своих объектов. Хорошо это или плохо, но я не сталкивался ни с одним сценарием, когда кто-то нарушил это соглашение. Дейви Брайон объясняет это очень подробно здесь. (Он ссылается на вашу точку зрения, что да, вы можете пометить классы как не ленивую загрузку. Но, так как nHibernate тогда не будет создавать никаких ваших прокси ты застрял.)

Я не знаю, полезно ли это, но именно так Касл делает это. Теперь, когда (если вы используете 2.1) , вы можете выбрать, какой генератор прокси использовать , переход к одному из других вариантов может позволить вам генерировать прокси таким образом это соответствует вашим потребностям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...