Мое приложение C# 3.5 использует SQL Server 2008 R2, NHibernate и CastleProject ActiveRecord. Приложение импортирует электронные письма в базу данных вместе с их вложениями. Сохранение электронных писем и вложений выполняется по 50 электронных писем в новом сеансе и области транзакции, чтобы убедиться, что они не хранятся в памяти (в некоторых почтовых ящиках может быть 100 000 писем).
Изначально электронные письма сохраняются очень быстро. Однако ближе к 20 000 писем производительность резко снижается. С помощью dotTrace я получил следующую картину:
Очевидно, что когда я сохраняю вложение, NHibernate пытается понять, действительно ли оно должно быть сохранено, и, возможно, сравнивает с другими вложениями в сеансе. Для этого он сравнивает их побайтно, что занимает почти 500 секунд (для снимка на картинке) и 600M операций счетчика.
Все это выглядит дико, особенно когда я точно знаю, что SaveAndFlush действительно должен сохранить вложение без каких-либо проверок: я точно знаю, что оно новое и его нужно сохранить.
Однако я не могу понять, как указать NHibernate избегать этой проверки (IsUpdateNecessary). Пожалуйста, порекомендуйте.
P.S. Я не уверен, но может показаться, что снижение производительности ближе к 20K не связано с наличием в памяти некоторых старых писем: я заметил, что в почтовом ящике, с которым я работаю, большие письма сохраняются позже, чем маленькие, поэтому проблема может быть только в сравнение вложений.
Обновление: Похоже, мне нужно что-то вроде StatelessSessionScope, но документации по нему нет даже на сайте CastleProject! Если я сделаю что-то вроде
using (TransactionScope txScope = new TransactionScope())
using (StatelessSessionScope scope = new StatelessSessionScope())
{
mail.Save();
}
это не удается, за исключением того, что сохранение не поддерживается сеансом без сохранения состояния. Я должен вставлять объекты в сеанс, но у меня нет сеанса (только SessionScope, который добавляет к SessionScope только один метод OpenSession, который принимает странные параметры).