Эффективная загрузка нескольких специальных объектов NHibernate с поддержкой кэша - PullRequest
2 голосов
/ 31 января 2012

Мне нужно эффективно загружать большое количество объектов на основе списка специальных идентификаторов. К сожалению, это не похоже на то, что кэш 2-го уровня проверяется первым при выполнении Restrictions.In(Projections.Id(), ids) критериев запросов.

Полагаю, я ищу что-то похожее на ISession.Load, которое принимает коллекцию идентификаторов (вместо одного) и выполняет запрос IN только для сущностей, которые не могут быть найдены ни в кеше 1-го, ни в 2-м уровне. , Если ничего подобного не существует, то какой самый простой способ проверить два кэша вручную, не прибегая к рефлексии?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2012

Комментарий Даррена Коппа абсолютно прав, пакетная обработка автоматически обрабатывает это, если вы не забываете использовать 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;
    }
}
0 голосов
/ 31 января 2012
var entities = adhocIds
    .Select(session.Load<TEntity>)
    .ToList();

var notloaded = entities
    .Where(entity => !NHibernateUtil.IsInitialized(entity))
    .Select(session.GetIdentifier)
    .ToList();

// we don't need the resultset, we just load it
// so the proxies hit the cache instead of the DB
session.CreateCriteria<TEntity>()
    .Add(Restrictions.In(Projections.Id(), notloaded))
    .List();

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