Пользовательская реализация сеанса NHibernate - PullRequest
0 голосов
/ 08 сентября 2011

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

Объект с самым низким уровнем детализации (т. Е. Корень моих агрегатов) имеет ряд строк свойств , которые не могут (или не имеют смысла) моделироваться столько раз, сколькодля одного (например, «Комментарий»).В действительности, поля в БД, соответствующие этим свойствам, принимают только очень много значений (например, потому что большинство - но не все - комментарии генерируются машиной), в результате чего при гидратации тонн объектов много памяти тратится впустуютысячи и тысячи экземпляров строк с одинаковыми значениями.

Я думал об прозрачной оптимизации этого сценария путем создания собственного пользовательского типа NHibernate, который улучшает StringType NHibernate путем переопределения NullSafeGet() и поиска в словаре.возвращать один и тот же экземпляр каждого вхождения строки снова и снова.Другими словами, я бы выполнял что-то вроде интернирования.Использование пользовательского типа позволяет мне выбирать, какие свойства каких объектов следует «интернировать», просто указав этот тип в файлах сопоставления.

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

Проблема в том, что я не могу найти способ «внедрить» пользовательскую реализацию сеанса NHibernate в NHibernateсам по себе, чтобы IType мог получить к нему доступ в NullSafeGet() времени, не считая создания моей собственной ветки кода NHibernate.

Есть ли способ обеспечить NHibernate пользовательской реализацией сеанса?

1 Ответ

4 голосов
/ 08 сентября 2011

Я вижу три разных подхода к решению этой проблемы:

1. Используйте перехватчик

В Interceptor вы получаете:

void AfterTransactionBegin(ITransaction tx);
void BeforeTransactionCompletion(ITransaction tx);

2. Завершение открытия и закрытия сессии:

Открытие и закрытие сессии - явный вызов. Должно быть легко обернуть это в метод.

public ISession OpenSession()
{
  var session = sessionFactory.CreateSession();
  StringType.Initialize();
}

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

3. Не присоединяйте строковый кеш к сеансу

Это не должно быть связано с сеансом. Строки являются неизменяемыми объектами, это не повредит, когда вы смешиваете их между сессиями. Чтобы избежать неограниченного роста кэша, вы можете написать свой собственный или использовать существующий «последний использованный» кэш. Достигнув определенного размера, он выбрасывает самые старые предметы.

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

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