将自定义实体附加到会话,因为它刚刚被刷新或加载(实现黑客)

时间:2015-10-29 10:19:31

标签: c# hibernate nhibernate

我有一个插入StatelessSession的实体(手工构建)。它有一个深藏的收藏品结构。我想在普通Session中使用此对象,以便跟踪并使用Commit保存更改。我需要欺骗NHibernate认为它自己创建了这个实体。这应该在没有实际访问数据库的情况下完成。

以下是NH源链接:https://github.com/nhibernate/nhibernate-core/

我整天调试了它,但仍然没有解决方案。问题是所有集合都应该包含IPersistentCollection。我实现了这一点,但封装器仍未以正确的方式初始化。

var m = s.FlushMode;
s.FlushMode = FlushMode.Never; // do not update anything until I say
try
{
    s.Lock(DbEntity, LockMode.None); // throws "reassociated object has dirty collection reference"
}
catch
{
    s.Lock(DbEntity, LockMode.None); // second works but then updates db on flush!

    var sessionImpl = s as SessionImpl;

    var state = sessionImpl.PersistenceContext.GetEntry(DbEntity);

    IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(state.EntityName);

    WrapVisitor visitor = new WrapVisitor(sessionImpl);
    // substitutes into values by side-effect
    object[] propertyValues = persister.GetPropertyValues(DbEntity, sessionImpl.EntityMode);
    visitor.ProcessEntityPropertyValues(propertyValues, persister.PropertyTypes);
    persister.SetPropertyValues(DbEntity, propertyValues, sessionImpl.EntityMode);

    var lockMode = state.LockMode;
    state.PostUpdate(DbEntity, propertyValues, state.Version);
    state.LockMode = lockMode;

    var types = persister.PropertyTypes;
    // should initialize wrappers Role, Key and Snapshot
    // will this handle nested collections? I don't know...
    for (int i = 0; i < propertyValues.Length; i++)
    {
        var collection = propertyValues[i] as IPersistentCollection;
        if (collection == null) continue;
        var collectionType = (CollectionType)types[i];
        ICollectionPersister collectionPersister = sessionImpl.Factory.GetCollectionPersister(collectionType.Role);
        // nope, this doesn't work :((
        sessionImpl.PersistenceContext.AddInitializedCollection(collectionPersister, collection, null);
        //sessionImpl.PersistenceContext.AddInitializedDetachedCollection(collectionPersister, collection);
    }
    // now collections should be initialized as they were attached to session
    s.Clear(); // second attempt should now work
    s.Lock(DbEntity, LockMode.None); // exception, IPersistentCollection doesn't have a key and role!!!
    s.FlushMode = m; // updates on
    // work with DbEntity here
    curTr.Commit();
}

我知道我不应该做这件事。但是,当我需要更新一个小房产时,我不喜欢NH读取数据库的方式。我没有使用二级缓存,因为我使用有状态服务包装我的实体并手动缓存它们。我不希望将相同的数据缓存两次。

那怎么办呢?

0 个答案:

没有答案