Несколько SessionFactories в службе Windows с NHibernate

У меня есть Веб-приложение, которое соединяется с 2 DBS (одно ядро, другой регистрирующийся DB).

Я должен теперь создать службу Windows, которая будет использовать ту же бизнес-логику / Доступ к данным DLLs. Однако, когда я пытаюсь сослаться на 2 фабрики сессии в Сервисном Приложении и назвать фабрику. GetCurrentSession () метод, я получаю сообщение об ошибке "Никакая сессия, связанная с текущим контекстом".

У кого-либо есть предложение о том, как это может быть сделано?

public class StaticSessionManager
{
    public static readonly ISessionFactory SessionFactory;
    public static readonly ISessionFactory LoggingSessionFactory;

    static StaticSessionManager()
    {
         string fileName = System.Configuration.ConfigurationSettings.AppSettings["DefaultNHihbernateConfigFile"];
         string executingPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
         fileName = executingPath + "\\" + fileName;
         SessionFactory = cfg.Configure(fileName).BuildSessionFactory();

         cfg = new Configuration();
         fileName = System.Configuration.ConfigurationSettings.AppSettings["LoggingNHihbernateConfigFile"];
         fileName = executingPath + "\\" + fileName;
         LoggingSessionFactory = cfg.Configure(fileName).BuildSessionFactory();
    }
}  

Конфигурационный файл имеет установку:

<property name="current_session_context_class">call</property>

Сервис настраивает фабрики:

private ISession _session = null;
private ISession _loggingSession = null;
private ISessionFactory _sessionFactory = StaticSessionManager.SessionFactory;
private ISessionFactory _loggingSessionFactory = StaticSessionManager.LoggingSessionFactory;

...

_sessionFactory = StaticSessionManager.SessionFactory;
_loggingSessionFactory = StaticSessionManager.LoggingSessionFactory;

_session = _sessionFactory.OpenSession();
NHibernate.Context.CurrentSessionContext.Bind(_session);
_loggingSession = _loggingSessionFactory.OpenSession();
NHibernate.Context.CurrentSessionContext.Bind(_loggingSession);

Таким образом, наконец я пытаюсь назвать корректную фабрику:

ISession session = StaticSessionManager.SessionFactory.GetCurrentSession();

Кто-либо может предложить лучший способ обработать это?
Заранее спасибо!
Ограбить

6
задан Rob Taylor 28 May 2010 в 17:09
поделиться

1 ответ

Первое, что я могу предложить, - сделать оба ваших экземпляра ISessionFactory статическими. Это должны быть синглтоны, поскольку их создание очень дорогое.

РЕДАКТИРОВАТЬ №1

Вы бы порекомендовали мне создавать сеансы, когда они мне нужны, или оставлять их открытыми?

ISession API обрабатывает свое соединение внутренне. Через некоторое время, если не требуется взаимодействия с базовой базой данных, соединение закрывается, хотя ваш ISession сохраняет свой экземпляр соединения. Когда ему нужно выполнить некоторые другие транзакции с базой данных, он повторно открывает ранее использованное соединение.

Чтобы ответить на ваш вопрос, предпочтительным подходом является использование экземпляра ISession API для каждой страницы (Web) или формы (Desktop). Например, предположим, что у вас есть бухгалтерское программное обеспечение, и у пользователя есть некоторые обязанности по управлению клиентами. Затем, когда ваш CustomerMgmtForm загружается, вы должны предоставить экземпляр ISession , чтобы он мог загружать ваших клиентов, отслеживать ваши изменения, удаления и новых клиентов, созданных (после присоединения к ISession , так что когда вы вызываете метод SaveOrUpdate () , ISession знает, что он должен делать с отслеживаемыми изменениями и временными объектами.

Вам интересно, почему один экземпляр на страницу или на форму?

Поскольку ISession API отслеживает все изменения, происходящие с объектом, представьте, как только вы загрузите своих клиентов, поставщиков и некоторые другие объекты, о которых вы должны позаботиться в своем приложении. Каждое из изменений производится в отношении клиентов, они не имеют права на поставщиков. Но эти клиенты по-прежнему будут там, потому что это экземпляр ISession , который вы использовали для своих клиентов! Затем требования вашего приложения к памяти растут с увеличением количества загружаемых объектов. Кроме того, известная проблема заключается в том, что когда ISession становится слишком большим в памяти, это может вызвать некоторые утечки памяти, а затем NHibernate считает сеанс более недействительным, удаляя все ваши несохраненные изменения и все остальное, поскольку сеанс, который отслеживал ваши объекты, теперь недействителен.

В дополнение к этому, когда вы открываете, скажем, CustomerMgmtForm , вам нужно будет управлять сущностями Customer . Скорее всего, вам не придется отслеживать своих клиентов после того, как вы закроете форму или даже откроете SuppliersMgmtForm , в которой вы будете управлять своими поставщиками. Таким образом у вас будет два экземпляра ISession API: первый - customerMgmtSession , другой - suppliersMgmtSession . Таким образом, они никогда не должны становиться слишком большими, чтобы вызвать утечку памяти, поскольку у них обоих есть свои собственные сущности, которые нужно обрабатывать или о которых нужно заботиться. Оба полностью независимы друг от друга.

Следуя этому подходу, вы должны закрыть и удалить экземпляр ISession API в событии FormClosing для Windows Forms или любого другого эквивалента в Интернете. Итак, теперь в службе Windows вам нужно решить, какая ситуация является идеальной, и решить, где она будет наиболее подходящей для ваших нужд, в зависимости от того, что делает ваша служба.

Одно но: если ваша служба не требует отслеживания ваших изменений или чего-либо еще в ваших объектах, возможно, более подходящим для использования будет API IStatelessSession . Используя его, я определенно предлагаю вам открывать или создавать экземпляр сеанса без сохранения состояния только тогда, когда вам нужно взаимодействовать с базовой базой данных, поскольку нет смысла поддерживать IStatelessSession , поскольку он не работает » • Предоставлять ресурсы для отслеживания изменений, внесенных в ваши объекты. Это главное и, возможно, единственное, если я правильно помню, разница между API ISession и IStatelessSession .

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

Выполнение этого, как указано выше в моем РЕДАКТИРОВАТЬ №1 , также может помочь вам решить вашу проблему, поскольку вам никогда не придется вызывать ISessionFactory. GetCurrentSession () .

Надеюсь, это поможет! =)

4
ответ дан 17 December 2019 в 07:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: