Darren Kopp «s комментарий абсолютно прав, пакетирование автоматически обрабатывает это при условии, вы помните, чтобы использовать ISession.Load
вместо ISession.Get
и не прикасайтесь ни к каким объектам прокси до тех пор, пока вы закончите подгружать их всех.
Однако я решил поделиться другим новым решением, которое я придумал для сред, которые не имеют ленивой загрузки или пакетной обработки. Подклассифицируя класс DefaultLoadEventListener
и возвращая null из метода LoadFromDatasource
, можно загрузить объект, если он существует в кешах 1 или 2 уровня, не касаясь базы данных. Это просто вопрос получения отсутствующих объектов в одном запросе IN и переплетения их в упорядоченный набор результатов.
static IList<T> LoadAll<T>(this ISession session, params object[] ids)
where T : class
{
var results = new T[ids.Length];
var uncachedIds = new Dictionary<object, int>();
var helper = new LoadHelper();
for (var i = 0; i < ids.Length; i++) {
var id = ids[i];
var evt = new LoadEvent(id, typeof (T).FullName, false,
(SessionImpl) session);
helper.OnLoad(evt, LoadEventListener.Get);
var entity = (T) evt.Result;
if (entity != null) {
results[i] = entity;
}
else {
uncachedIds.Add(id, i);
}
}
if (uncachedIds.Count > 0) {
var entities = session.CreateCriteria<T>()
.Add(Restrictions.In(Projections.Id(), uncachedIds.Keys))
.List<T>();
foreach (var entity in entities) {
var id = session.GetIdentifier(entity);
var index = uncachedIds[id];
results[index] = entity;
}
}
return results;
}
Вот очень простой LoadHelper
класс, который делает тяжелую работу:
private class LoadHelper : DefaultLoadEventListener
{
protected override object LoadFromDatasource(LoadEvent evt,
IEntityPersister persister,
EntityKey keyToLoad,
LoadType options)
{
return null;
}
}
Что случилось с Session.load? –
@DarrenKopp Вызов 'Load' для каждого идентификатора будет выдавать несколько запросов к базе данных. Я хочу, чтобы один запрос пропускал уже кэшированные объекты. –
Не обязательно. Загрузка будет возвращать прокси, но не будет выдавать запрос. Запрос выполняется, когда что-то на объекте обращается, но до его обращения он не будет запрашивать базу данных. NHibernate также имеет пакетную обработку запросов, поэтому вы можете вызвать нагрузку в тысячу раз и с размером партии 200, получить только 50 запросов к базе данных. –