Свободный NHibernate ISessionManager или эквивалентный - PullRequest
2 голосов
/ 03 июля 2011

Я довольно новичок в мире FNH и NH, поэтому будьте осторожны: P

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

Макет приложения, который я создал до сих пор, имеет синглтон "База данных", который имеетразличные методы, такие как Save (), Refer () и List ().При вызове Refer () сеанс открывается, данные извлекаются и сеанс удаляется;Это означает, что при попытке получить доступ к загруженному в ленивое свойство из возвращенного объекта сеанс недоступен.Пример: Database.Refer ("username"). Person, так как Person загружен лениво, а сессия уже закрыта.

Я читал, что у Castle есть SessionManager, который можно использовать для этого самого сценария, но либоэто поздние ночи или отсутствие кофе, я не могу понять, как подключить FNH, чтобы использовать этот менеджер, поскольку, в духе замка, все определено в конфигурационных файлах.

Я пропустилчто-то или это нельзя сделать?Существуют ли какие-либо другие менеджеры сеансов (или даже более подходящие соглашения), на которые мне следует обратить внимание?

Спасибо за любую помощь в этом вопросе.

Ответы [ 2 ]

0 голосов
/ 13 июля 2011

Для любого из вас, кто все еще ищет ответы на этот вопрос, я поделюсь с вами тем, что у меня есть до сих пор.

Это лишь очень простой обзор структуры, которую я решил использовать,и это далеко не единственное решение этой проблемы.

Основная схема моего кода выглядит следующим образом:

  • Репозиторий NHibernate (ссылается на мою сборку модели и сборку UoW)
    • На основе реализации репозитория HibernatingRhino, модифицированной в соответствии с моими потребностями.Найдено здесь: http://ayende.com/Wiki/Rhino+Commons.ashx
      public T Get(Guid Id)
      {
          return WrapUOW(() =>
          {
              using (Audit.LockAudit())
                  return (T)Session.Get(typeof(T), Id);
          });
      }
      public void LoadFullObject(T partial)
      {
          if (partial == null)
              throw new ArgumentNullException("partial");
      
          if (partial.Id == Guid.Empty)
              return;
      
          WrapUOW(() =>
          {
              using (Audit.LockAudit())
              {
                  LazyInitialiser.InitialiseCompletely(partial, Session);
              }
          });
      }
      public T SaveOrUpdate(T entity)
      {
          using (Audit.LockAudit())
          {
              With.Transaction(() =>
              {
                  Enlist(entity);
      
                  Session.SaveOrUpdate(entity);
      
                  entity.HasChanged = false;
              });
          }
      
          return entity;
      }
      protected void Enlist(T instance)
      {
          if (instance != null && instance.Id != Guid.Empty && !Session.Contains(instance))
              using (Audit.LockAudit())
              {
                  Session.Update(instance);
              }
      }
      
      
    • Ссылка на классный маленький вспомогательный класс под названием «Ленивый инициализатор для NHibernate», найденный здесь: http://www.codeproject.com/KB/cs/NHibernateLazyInitializer.aspx
    • Здесь также содержатся методы расширения для сохранения., Delete и LoadFullObject
    • Немного нарушили стандарты в этой сборке, также создав метод WrapUOW, чтобы упростить часть моего кода
      protected static T WrapUOW(Func action)
      {
          IUnitOfWork uow = null;
      
          if (!UnitOfWork.IsStarted)
              uow = UnitOfWork.Start();
      
          T result = action();
      
          if (uow != null)
              uow.Dispose();
      
          return result;
      }
  • NHibernate Единица работы (ссылается на моюсборка модели)
    • Также основано на реализации UoW HibernatingRhino и изменено для соответствия
  • Представление - не важно, просто требуется для реализации MVVM
    • Связываетзначения из ViewModel
  • Модель
    • Содержит мои классы сущностей и файлы отображения гибернации
  • ViewModel
    • Содержит два основных базовых класса представления, ListPage и MaintenancePage
    • Базовый класс ListPage просто вызывает метод Repository List на основе типа объекта, который мы перечисляем.Это загружает обезвоженный список сущностей.
    • MaintenancePage берет экземпляр сущности из ListPage и вызывает метод Repository.LoadFullObject для повторной гидратации сущности для использования на экране.
      • Это позволяет использовать привязку на экране.
      • Мы также можем безопасно вызывать метод Repository.SaveOrUpdate с этой страницы
0 голосов
/ 03 июля 2011

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

Из того, что я могуВы понимаете, что ваша публикация заключается в том, что вы пытаетесь представить сущность вашему представлению (с некоторыми лениво загруженными свойствами), что уже является плохой идеей, поскольку приводит к неприятным LazyInitializationException(s).

.различие между вашим data-model и вашим domain model.Ключевая концепция была описана в этом блоге:

Ayende @ Rahien http://ayende.com/blog/4054/nhibernate-query-only-properties

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

Я бы также посмотрел на запроскоторый выбирает вашу сущность, так как мне кажется, что вы пытаетесь получить данные, которые являются лишь частью вашей модели - в данном случае Person.Это может привести к серьезным проблемам, таким как n+1 selects:

Что такое SELECT N + 1?

Так что в целом, я думаю, вам следует сосредоточиться на какВ вашем приложении все структурировано вместо поиска SessionManager, поскольку это не решит все ваши проблемы.

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