Ленивая загрузка не работает с NHibernate - PullRequest
0 голосов
/ 03 марта 2011

Использование lazy = "true" в моих классах приводит к тому, что мое приложение работает отлично, но производительность ужасна.Я включил это обратно, когда создавал это из учебника, и просто хотел, чтобы что-то работало как можно быстрее.(Я использовал этот урок: http://geekswithblogs.net/BobPalmer/archive/2010/04/23/mapping-object-relationships---quickstart-with-nhibernate-part-3.aspx, который был очень полезен для получения чего-то, что работало быстро)

Мне не нужно загружать все эти классы "многие к одному", когда мне просто нужноиспользовать один объект, поэтому имеет смысл снова включить отложенную загрузку.Затем я посмотрел на объекты и не увидел ничего, кроме исключений для этих классов «многие к одному» внутри моих основных объектов.Когда я пытаюсь использовать эти свойства позже, я получаю следующую ошибку:

"Could not initialize proxy - no Session." 

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

class SessionProvider {
    private static ISessionFactory _sessionFactory;
    private static Configuration _config;

    public static ISessionFactory SessionFactory {
        get {
            if (_sessionFactory == null) {
                _sessionFactory = Config.BuildSessionFactory();
            }
            return _sessionFactory;
        }
    }

    private static Configuration Config {
        get {
            if (_config == null) {
                _config = new Configuration();
                _config.AddAssembly(Assembly.GetCallingAssembly());
            }
            return _config;
        }
    }
}

, который затем используется моими репозиториями следующим образом:

using (var session = GetSession()) { ... }

, который получает сеанс из этой функции:

private static ISession GetSession() {
        return SessionProvider.SessionFactory.OpenSession();
}

Итак, мой вопрос: что мне здесь делать?Держать сеанс открытым?Сделать это статичным во всех репозиториях?У меня недостаточно опыта работы с NHibernate, чтобы понять, как это работает.Мой приоритет сейчас - только чтение из базы данных, если это что-то меняет.Это происходит в библиотеке кода, которая в конечном итоге будет использоваться как на нашем веб-сайте, так и в различных приложениях C # .Net.

Ответы [ 4 ]

2 голосов
/ 03 марта 2011

Рекомендуемый подход заключается в использовании шаблона работы . Другой вариант для вас - использовать готовую загрузку, если вы знаете, что вам понадобятся конкретные объекты заранее.

1 голос
/ 06 марта 2011

Вы управляете своим сеансом на микроуровне, открывая и закрывая его в хранилище. Это не только нарушает ленивую загрузку, но и сильно снижает производительность.

Вместо этого управление сеансом должно осуществляться с более грубым подходом.

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

Просто посмотрите сеанс за запросом, примеров много.

0 голосов
/ 07 марта 2011

Простая проблема заключается в том, что вы пытаетесь получить доступ к пока еще не загруженным значениям, когда связанный с ним объект был удален.

Объект Session NHibernate предназначен для следования за единицейшаблон работы.То есть вы создаете один сеанс для каждого юнита, который хотите завершить.

Говоря прямо, вы должны поддерживать экземпляр Session живым (не утилизированным) до тех пор, пока вы «не закончите» с объектами, связанными сэта сессияЭто означает, что ваш объект сеанса становится областью вашей работы:

using(var session = GetSession())
{
    // Load some objects.
    // Manipulate some values.
    // Commit changes.
}

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

0 голосов
/ 04 марта 2011

Вы не говорите, является ли ваше приложение веб-приложением (например, ASP.NET MVC) или консольным / графическим интерфейсом / сервисным приложением. Общая проблема с отложенной загрузкой ORM в веб-приложениях MVC заключается в том, что сеанс закрывается в конце метода действия контроллера, объект прокси-объекта передается в представление, которое затем пытается перечислить некоторую загруженную коллекцию, которая завершается неудачно из-за сессия была утилизирована. Решение этой проблемы называется шаблоном «Открыть сеанс в представлении» (по крайней мере, в мире Java), который обычно включает использование фильтра для открытия сеанса в начале веб-запроса, гарантирующего, что сеанс передается любому контроллеру или другому объект, запрашивающий его (это, как правило, будет управляться вашим контейнером IoC), тогда сеанс все еще активен, когда представление выполняется и лени-загружает свойства.

Работая с Hibernate как на Java, так и на .Net в нескольких системах, я обычно придерживаюсь мнения, что отложенная загрузка - это немного проклятие. Несмотря на то, что это удобно, оно часто требует дополнительного подключения (например, что-то для поддержки шаблона «Открыть сеанс в представлении») и часто снижает производительность. Вероятно, лучше использовать готовую загрузку для тех коллекций, которые, как вы знаете, с большой вероятностью будут доступны. Анализ того, какие коллекции нужно загружать с нетерпением, заставляет вас лучше понять профиль доступа к данным вашего приложения, что поможет вам лучше понять характеристики производительности приложения, что может быть только хорошо!

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