2009-10-29 2 views
1

У меня возникла ситуация, когда мне нужно загрузить часть графического объекта с использованием пользовательского SQL (по соображениям производительности). Поэтому я загружаю эту коллекцию, используя свой собственный SQL (ISession.CreateSQLQuery()), а затем присваиваю этот список свойству другому объекту объекта.NHibernate: есть ли способ пометить объект как НЕ грязный?

Проблема заключается в том, что когда я присваиваю список свойству, это заставляет этот объект грязно вместе со всеми объектами в списке, поэтому, когда я иду для сохранения объекта, он выполняет сотни запросов, чтобы сохранить весь список. Есть ли способ, который я могу указать, что объект НЕ грязный (после того, как я загрузил его сам)?

(Да, я знаю, что я мог бы отключить каскад = «копи-обновление», но я действительно не хочу, чтобы сделать это, если я могу избежать его.)

+0

Не могли бы вы отредактировать свое сообщение с привязками сущностей и всем связанным кодом? Благодарю. –

ответ

3

Я думаю, что есть функциональность до выселение юридическое лицо.

Это означает, что больше не связано с NHibernate.


ОБНОВЛЕНО после различных комментариев Йона:

  • Если вы хотите, чтобы NHibernate управлять объект, то есть обнаружить, если она грязная, а затем сохранить его удалось.
  • Если нет, Evict() он не будет управляться. Вы все равно можете сохранить его вручную и так далее, это просто не будет автоматически для вас.

Я не вижу золотую середину, между автоматический и ручной ...

Обратите внимание, что вы можете по-прежнему сохраняются различными способами, как сохранение вручную родительскую сущность, набор дочерние объекты и т. д. Многие вещи все еще возможны.

+0

Но тогда вся ленивая загрузка больше не работает на этом объекте, так что это не сработает. –

+0

Да, есть определенные проблемы вокруг проблемы. Похоже, было бы намного проще, хотя если бы можно было просто сказать NH, что что-то не грязное. Спасибо за помощь. –

+0

@ Jon Добро пожаловать. Спасибо за ваше хорошее отношение:) - – KLE

2

Расширяя KLEs ответ, я бы:

  1. выселить() родительский объект
  2. Загрузить список потомков
  3. Приложите список детей к родительской сущности
  4. Merge () все это обратно в nHibernate

В этот момент я считаю, что NHibern съедает все чистое.

+0

Ничего себе, у вас есть первая точка SO, отвечая на мой вопрос. Я чувствую себя особенным! –

+0

После того, как вы слияете() что-то, NH все еще, что это грязно. –

1

Можете ли вы просто удалить свойство, которое вы используете для хранения данных, извлеченных вручную, из отслеживания NHibernates?

+0

Нет, потому что мне нужно это, чтобы сохранить это свойство. –

1

Предполагая, что вы не сохраняете свойство, которому присвоен список, вы можете удалить это свойство из сопоставления NHibernate. Я не тестировал это, но я ожидаю, что присвоение этому свойству не приведет к тому, что IsDirty() вернет true.

EDIT: Хорошо, попробуйте попробовать. Загрузите объект из IStatelessSession, вызовите свой собственный SQL и назначьте свойство. Затем заблокируйте объект в новом ISession и продолжайте работать с ним.Я думаю, что Lock будет каскадом к дочерним объектам, если ваш каскадный параметр является полностью или все-удалить-сиротой. Если блокировка не каскадируется, вам придется вручную перейти к графику объекта.

+0

Мне нужно это, чтобы сохранить собственность. –

0

Вы можете использовать перехватчик, а затем переопределить метод FindDirty.

0

Я не помню, где я получил от этого, но у меня есть класс расширений сесии, один из которых это:

public static Object GetOriginalEntityProperty(this ISession session, Object entity, String propertyName) 
{ 

    ISessionImplementor sessionImpl = session.GetSessionImplementation(); 

    IPersistenceContext persistenceContext = sessionImpl.PersistenceContext; 

    EntityEntry oldEntry = persistenceContext.GetEntry(entity); 



    if ((oldEntry == null) && (entity is INHibernateProxy)) 
    { 

     INHibernateProxy proxy = entity as INHibernateProxy; 

     Object obj = sessionImpl.PersistenceContext.Unproxy(proxy); 

     oldEntry = sessionImpl.PersistenceContext.GetEntry(obj); 

    } 

    if (oldEntry == null) // I'm assuming this means the object is transient and that this is the way to treat that 
     return false; 

    String className = oldEntry.EntityName; 

    IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className); 

    Object[] oldState = oldEntry.LoadedState; 

    Object[] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode); 

    Int32[] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl); 

    Int32 index = Array.IndexOf(persister.PropertyNames, propertyName); 



    Boolean isDirty = (dirtyProps != null) ? (Array.IndexOf(dirtyProps, index) != -1) : false; 



    return ((isDirty == true) ? oldState[index] : currentState[index]); 

} 

Если вы получаете оригинальное значение с помощью этого метода и присвоить его постоянное свойство больше не будет грязным.