NHibernate:有没有办法将对象标记为不脏?

时间:2009-10-29 12:12:16

标签: nhibernate

我有一种情况需要使用自定义SQL加载对象图的一部分(出于性能原因)。所以我使用自定义SQL(ISession.CreateSQLQuery())加载此集合,然后将该列表分配给另一个实体对象上的属性。

问题在于,当我将列表分配给属性时,它会使该实体与列表中的所有对象一起变脏,因此当我去保存对象时,它会执行数百个查询来保存整个列表。有没有办法可以指定对象不脏(在我自己加载之后)?

(是的,我知道我可以关闭cascade =“save-update”,但如果可以避免的话,我真的不想这样做。)

6 个答案:

答案 0 :(得分:3)

我认为有一种功能可以逐出一个实体。

这意味着它不再与NHibernate连接。


在Jon的各种评论之后

更新

  • 如果您希望NHibernate 管理该对象,即检测它是否脏,则将其保持管理。
  • 如果没有,Evict()它,它将无法管理。您仍然可以手动等保存它,只是它不会自动为您完成。

我看不到自动和手动之间的任何中间地带......

  

请注意,您仍然可以通过各种方式持久存储,例如手动保存父实体,一组子实体等等......许多事情仍然存在。

答案 1 :(得分:2)

扩展KLE的回答,我会:

  1. Evict()父实体
  2. 加载子列表
  3. 将子列表附加到父实体
  4. 将整个事物合并()回到nHibernate
  5. 那时我相信NHibernate会认为一切都很干净。

答案 2 :(得分:1)

您是否可以删除用于存储此NHpennates跟踪手动提取数据的属性?

答案 3 :(得分:1)

假设您没有持久化分配列表的属性,您可以从NHibernate映射中删除该属性。我没有对此进行测试,但我的期望是分配给该属性不会导致IsDirty()返回true。

编辑:好的,试试吧。从IStatelessSession加载对象,调用自定义SQL并分配属性。然后将对象锁定到新的ISession并继续使用它。我认为如果您的级联设置是全部或全部 - 删除 - 孤立,则锁将级联到子对象。如果Lock没有级联,那么您将不得不手动遍历对象图。

答案 4 :(得分:0)

您可以使用拦截器,然后覆盖FindDirty方法。

答案 5 :(得分:0)

我不记得我从哪里得到这个,但我有一类Session扩展,其中一个就是:

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]);

}

如果使用此方法获取原始值并将其分配给持久属性,则它将不再是脏的。