检查会话是否脏,但不要刷新

时间:2015-07-23 20:48:30

标签: nhibernate

我确定我已经看过这个问题,但我不能使用正确的关键字,因为我现在无法找到任何关键字:

我有一个使用NHibernate持久性的桌面应用程序。我想使用会话的isDirty属性来通知用户是否有任何持久数据已被更改,向他显示关闭按钮或应用取消按钮,具体取决于。

问题是调用isDirty会导致至少某些数据被刷新到数据库,尽管我的 FlushMode 从不。我有兴趣知道为什么isDirty感觉必须清除这些更改,但更重要的是我想知道如何在没有刷新的情况下获取此信息

顺便说一下:由于我没有在整个时间内处理事务,用户编辑表单上的信息,我认为任何刷新的更改都会保留,无论我是否最终提交其他内容

那么,有人可以告诉我如何在没有功能的情况下获得我想要的功能吗?

3 个答案:

答案 0 :(得分:1)

我自己没有这样做,但经过一些谷歌搜索,似乎有可能。如何只是循环遍历会话中的所有已加载实体并检查它们是否脏了?您甚至可以手动比较加载的实体与当前实体状态。

试试我在StackOverflow上找到的代码:(Source

var dirtyObjects = new List<object>();
var sessionImpl = session.GetSessionImplementation();
foreach (NHibernate.Engine.EntityEntry entityEntry in sessionImpl.PersistenceContext.EntityEntries.Values)
{
    var loadedState = entityEntry.LoadedState;
    var o = sessionImpl.PersistenceContext.GetEntity(entityEntry.EntityKey);
    var currentState = entityEntry.Persister.GetPropertyValues(o, sessionImpl.EntityMode);
    if (entityEntry.Persister.FindDirty(currentState, loadedState, o, sessionImpl) != null)
    {
        dirtyObjects.Add(entityEntry);
    }
}

如果您担心性能,可以在比较属性之前检查实体的类型:

Type t = Type.GetType(entityEntry.EntityName);
if (t == typeof(Employee))
{
    //do something
}

您也可以尝试制作自己的dirty-check interceptor

答案 1 :(得分:1)

我终于能够将注意力转回到此并制定解决方案,如下所示:

    /// <summary>
    /// Check whether a session is "dirty" without triggering a flush
    /// </summary>
    /// <param name="session"></param>
    /// <returns>true if the session is "dirty", meaning that it will update the database when flushed</returns>
    /// <remarks>
    /// The rationale behind this is the need to determine if there's anything to flush to the database without actually
    /// running through the Flush process.  The problem with a premature Flush is that one may want to collect changes
    /// to persistent objects and only start a transaction later on to flush them.  I have this in a Winforms application
    /// and this method allows me to notify the user whether he has made changes that need saving while not leaving a
    /// transaction open while he works, which can cause locking issues.
    /// <para>
    /// Note that the check for dirty collections may give false positives, which is good enough for my purposes but 
    /// coule be improved upon using calls to GetOrphans and other persistent-collection methods.</para>
    /// </remarks>
    public static bool IsDirtyNoFlush(this ISession session)
    {
        var pc = session.GetSessionImplementation().PersistenceContext;
        if (pc.EntitiesByKey.Values.Any(o => IsDirtyEntity(session, o)))
            return true;

        return pc.CollectionEntries.Keys.Cast<IPersistentCollection>()
            .Any(coll => coll.WasInitialized && coll.IsDirty);
    }

第一部分基本上是上面推荐的Shahin。最后一行是我一直缺少的。正如我在评论中提到的那样,它仍然没有内置的IsDirty()那么好,因为例如,那个人会认识到从持久集合中删除一个项目然后将其重新放入其中不再脏了,而我的方法会给出假阳性。尽管如此,它完全适合我的目的(以及其他大多数人,我想象)并且避免冲洗。

答案 2 :(得分:0)

我在viewmodel属性中进行了脏状态跟踪。在每个PropertyChanged我调用我的ViewModelBase类的MarkAsDirty()。这反映了一个属性,然后绑定到我的保存按钮命令。

但是如果你想使用NH跟踪,这个SessionExtension可以满足你的要求。