Я начинаю сессию в начале единицы работы и закрываю ее в конце. Единица работы выражается несколькими методами.NHibernate: Как получить экземпляр объекта из кеша сеанса?
В одном методе я загружаю объект, используя метод Get
. Таким образом, это сидит в кеше сеанса. Экземпляр объекта является локальным для метода. Поэтому, когда область метода заканчивается, экземпляр объекта недоступен. Но объект все еще находится в кеше сеанса.
Теперь второй метод создает новый экземпляр объекта и пытается его удалить. Это бросает NonUniqueObjectException
, как и ожидалось.
Ниже приводится решение, которое я могу себе представить, но не в состоянии реализовать:
public void Delete<T>(T instance) where T : BaseEntity
{
try
{
nhSession.Delete(instance);
}
catch(NonUniqueObjectException)
{
T instanceFromCache = GetInstanceFromCache<T>(instance);
nhSession.Evict(instanceFromCache);
nhSession.Delete(instance);
}
}
Если я могу получить экземпляр сущности из кэша сеанса каким-то образом, я могу Evict
его, и мы надеемся, что проблема будет решена. Но я не могу реализовать свой воображаемый метод GetInstanceFromCache
.
Я пробовал использовать nhSession.Get
, но это не помогает в моем сценарии. Имя основного ключа в моей базе данных не является «id», а также не совпадает с таблицами. В одной таблице это «Поле1», а в другом - «Поле2». Поэтому я не могу использовать что-то вроде nhSession.Get(instance.Id)
. Мой метод Delete<T>(T instance)
принимает экземпляр сущности для удаления в качестве параметра. Он не получает значение первичного ключа для удаления.
Для получения дополнительной информации, пожалуйста, обратитесь к моему вопросу other. Этот вопрос обсуждает проблему UPDATE и то, как я ее исправил; но сценарий схож.
Edit 1
Ответа на этот вопрос «@Ricardo Переса» не работает, как есть, но я его код немного изменен.
public static TEntity GetInstanceFromCache<TEntity>(this ISession nhSession, object instance) where TEntity : BaseEntity
{
var sessionImpl = nhSession.GetSessionImplementation();
foreach(BaseEntity baseEntity in sessionImpl.PersistenceContext.EntityEntries.Keys)
{
if(baseEntity is TEntity)
{
TEntity instanceFromCache = (TEntity)baseEntity;
if(nhSession.GetIdentifier(instanceFromCache) == nhSession.GetIdentifier(instance))
return baseEntity as TEntity;
}
}
return null;
}
Вызов nhSession.GetIdentifier(instance)
генерирует исключение TransientObjectException
(«экземпляр не был связан с этой сессией»), которая, как ожидается. Это связано с тем, что instance
неизвестно nhSession
. Любой способ получить идентификатор объекта, который НЕ связан с сеансом?
Если это прокси-сервер: http://stackoverflow.com/a/10328489/1486443. – Najera