Предотвращение отложенной загрузки в nHibernate - PullRequest
1 голос
/ 12 мая 2010

Я храню некоторые BLOB-объекты в моей базе данных, поэтому у меня есть таблица Document и таблица DocumentContent. Документ содержит имя файла, описание и т. Д. И имеет свойство DocumentContent.

У меня есть клиент Silverlight, поэтому я не хочу загружать и отправлять DocumentContent клиенту, если я не прошу об этом подробно, но у меня возникают проблемы при этом.

Я прочитал сообщение в блоге Дэви Брайон . Я попытался поместить в конфигурацию lazy = false и удалить модификатор виртуального доступа, но пока мне не повезло.

Каждый раз, когда я делаю Session.Get (id), DocumentContent извлекается через внешнее соединение. Я хочу, чтобы это свойство заполнялось только тогда, когда я включаю explicity в эту таблицу и запрашиваю его.

Любая помощь приветствуется.

Мое сопоставление NHibernate выглядит следующим образом:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Jrm.Model"
                   namespace="Jrm.Model">
  <class name="JrmDocument" lazy="false">
    <id name="JrmDocumentID">
      <generator class="native" />
    </id>

    <property name="FileName"/>
    <property name="Description"/>
    <many-to-one name="DocumentContent" class="JrmDocumentContent" unique="true" column="JrmDocumentContentID" lazy="false"/>
  </class>


  <class name="JrmDocumentContent" lazy="false">
    <id name="JrmDocumentContentID">
      <generator class="native" />
    </id>

    <property name="Content" type="BinaryBlob" lazy="false">
      <column name="FileBytes" sql-type="varbinary(max)"/>
    </property>

  </class>
</hibernate-mapping>

и мои классы:

[DataContract]   
    public class JrmDocument : ModelBase
    {
        private int jrmDocumentID;
        private JrmDocumentContent documentContent;
        private long maxFileSize;
        private string fileName;
        private string description;

        public JrmDocument()
        {
        }

        public JrmDocument(string fileName, long maxFileSize)
        {
            DocumentContent = new JrmDocumentContent(File.ReadAllBytes(fileName));
            FileName = new FileInfo(fileName).Name;
        }

        [DataMember]
        public virtual int JrmDocumentID
        {
            get { return jrmDocumentID; }
            set
            {
                jrmDocumentID = value;
                OnPropertyChanged("JrmDocumentID");
            }
        }               

        [DataMember]
        public JrmDocumentContent DocumentContent
        {
            get { return documentContent; }
            set
            {
                documentContent = value;
                OnPropertyChanged("DocumentContent");
            }
        }        

        [DataMember]
        public virtual long MaxFileSize
        {
            get { return maxFileSize; }
            set
            {
                maxFileSize = value;
                OnPropertyChanged("MaxFileSize");
            }
        }


        [DataMember]
        public virtual string FileName
        {
            get { return fileName; }
            set
            {
                fileName = value;
                OnPropertyChanged("FileName");
            }
        }

        [DataMember]
        public virtual string Description
        {
            get { return description; }
            set
            {
                description = value;
                OnPropertyChanged("Description");
            }
        }
    }



    [DataContract]
    public class JrmDocumentContent : ModelBase
    {
        private int jrmDocumentContentID;
        private byte[] content;

        public JrmDocumentContent()
        {
        }
        public JrmDocumentContent(byte[] bytes)
        {
            Content = bytes;
        }

        [DataMember]
        public int JrmDocumentContentID
        {
            get { return jrmDocumentContentID; }
            set
            {
                jrmDocumentContentID = value;
                OnPropertyChanged("JrmDocumentContentID");
            }
        }

        [DataMember]
        public byte[] Content
        {
            get { return content; }
            set
            {
                content = value;
                OnPropertyChanged("Content");
            }
        }
    }

Ответы [ 6 ]

2 голосов
/ 12 мая 2010

Вы должны использовать DTO для своей службы и оставить все с lazy = true вместо сериализации модели вашего домена. Это большой прирост производительности.

2 голосов
/ 12 мая 2010

Если вы хотите отложить загрузку, установите на вашей карте lazy = "true".

1 голос
/ 17 мая 2010

Первое эмпирическое правило:

  • не распространять ваши доменные объекты

http://martinfowler.com/bliki/FirstLaw.html

0 голосов
/ 01 апреля 2011

У меня была именно эта проблема.

Вот что я сделал:

  1. Создайте свой собственный прокси-сервер (используя Castle DynamicProxy, но вы можете попробовать другие), который возвращает null для всех неинициализированных свойств и коллекций и возвращает копию каждой инициализированной коллекции. Я обертываю каждый результат корневого объекта в моем сервисе таким прокси. Передача этого прокси в качестве возвращаемого значения моего сервиса - почти работает, за исключением того, что я не мог заставить мои прокси правильно сериализоваться. Вот почему я попробовал метод 2:

  2. (Ужасно) Глубоко клонируйте все мои сущности в новые объекты, пропуская неинициализированные свойства и коллекции. Это работает, но отстой.

  3. В настоящее время я пытаюсь использовать DataContractSurrogate, чтобы решить проблему в 1. или полностью заменить использование прокси. Проблема, которую я сейчас пытаюсь решить, заключается в том, что вы не можете «фильтровать» свойства объекта - вы не можете вернуть null из GetObjectToSerialize - это именно то, что я хочу вернуть, если объект Сериализованный - это неинициализированный прокси или коллекция NHibernate.

Я обновлю этот ответ, когда буду прогрессировать. В настоящее время я использую решение 2 как временное решение. Я бы поделился кодом, но в настоящее время это беспорядок (так как я не собирался использовать глубокое клонирование).

0 голосов
/ 26 мая 2010

Сценарий, который вы описали, является именно тем, для чего предназначена ленивая загрузка.

Вы хотите отобразить список, содержащий сводную информацию и при необходимости загрузить более тяжелые вещи.Это ленивая загрузка.Это "ленивый", потому что он избегает выполнения дополнительной работы, пока это абсолютно не нужно.

Вам нужно, чтобы JrmDocumentContent загружался лениво, и вы на этом пути.Чтобы получить это, вы должны удалить ленивый = ложь.lazy = true по умолчанию в nhibernate, но вы можете указать lazy = true, чтобы быть уверенным.Однако вам придется восстанавливать виртуалы.

Загрузка блогов лениво, как это или любое другое свойство, я думаю, теперь поддерживается в последнем выпуске nhibernate, установив lazy = true в определении свойства.

Метод, который вы использовали, разделяя тяжелое содержимое на отдельный класс / таблицу, был единственным способом ленивой загрузки большого двоичного объекта раньше.Я не знаю, какую версию nhibernate вы используете, но выбранная вами стратегия верна.Вы должны принять ленивую загрузку.Вам также необходимо удалить lazy = false в свойстве Content класса JrmDocumentContent.Кроме того, я не вижу другой причины, почему это не сработало.

0 голосов
/ 24 мая 2010

У меня была проблема с тем, где управлялись мои отношения (inverse = true), а также с моим созданием экземпляра сеанса во время его внедрения. Использование этого в сочетании с пользовательским DataContractSurrogate, который предотвращал некоторые проблемы отложенной загрузки, теперь работает .

Спасибо

var proxy = obj as INHibernateProxy; 
if (proxy != null) 
{ 
    var initializer = proxy.HibernateLazyInitializer; 
    if (initializer.IsUninitialized) 
    { 
        return Activator.CreateInstance(obj.GetType().BaseType); } 
    else 
    { 
        return initializer.GetImplementation(); 
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...