Комментарий Даррена Коппа абсолютно прав, пакетная обработка автоматически обрабатывает это, если вы не забываете использовать ISession.Load
вместо ISession.Get
и не трогаете ни один из прокси-объектов, пока незакончил извлекать их все.
Однако я подумал, что поделюсь другим новым решением, которое я придумал для сред, в которых не включена отложенная загрузка или пакетная обработка.Подклассом класса DefaultLoadEventListener
и возвратом нулевого значения из метода 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;
}
}