为什么我得到这个nhibernate NonUniqueObjectException?

时间:2011-09-30 23:57:07

标签: nhibernate session

以下方法使用新会话查询我的数据库。如果查询成功,它会将结果附加(通过“Lock”)到“MainSession”,用于支持来自数据绑定WinForms网格控件的延迟加载。

如果结果已经在MainSession中,我得到例外:

NHibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联:1,实体:BI_OverlordDlsAppCore.OfeDlsMeasurement

当我尝试使用Lock方法重新附加时。

即使我在尝试重新附加它之前从MainSession中逐出结果,也会发生这种情况。

我在更新结果时使用了相同的方法,但效果很好。

任何人都可以解释为什么会这样吗?

我应该如何调试此问题?

    public static OfeMeasurementBase GetExistingMeasurement(OverlordAppType appType, DateTime startDateTime, short runNumber, short revision)
    {
        OfeMeasurementBase measurement;

        var mainSession = GetMainSession();

        using (var session = _sessionFactory.OpenSession())
        using (var transaction = session.BeginTransaction())
        {
            // Get measurement that matches params
            measurement =
                session.CreateCriteria(typeof(OfeMeasurementBase))
                       .Add(Expression.Eq("AppType", appType))
                       .Add(Expression.Eq("StartDateTime", startDateTime))
                       .Add(Expression.Eq("RunNumber", runNumber))
                       .Add(Expression.Eq("Revision", revision))
                       .UniqueResult() as OfeMeasurementBase;

            // Need to evict from main session, to prevent potential 
            // NonUniqueObjectException if it's already in the main session
            mainSession.Evict(measurement);

            // Can't be attached to two sessions at once
            session.Evict(measurement);

            // Re-attach to main session
            // Still throws NonUniqueObjectException!!!
            mainSession.Lock(measurement, LockMode.None);

            transaction.Commit();
        }

        return measurement;
    }

1 个答案:

答案 0 :(得分:2)

我在Cross Session Operations找到Ayende帖后解决了这个问题。

解决方案是使用 ISession.Merge 在主会话中更新分离的测量值:

    public static OfeMeasurementBase GetExistingMeasurement(OverlordAppType appType, DateTime startDateTime, short runNumber, short revision)
    {
        OfeMeasurementBase measurement;

        var mainSession = GetMainSession();

        using (var session = _sessionFactory.OpenSession())
        using (var transaction = session.BeginTransaction())
        {
            // Get measurement that matches params
            measurement =
                session.CreateCriteria(typeof(OfeMeasurementBase))
                       .Add(Expression.Eq("AppType", appType))
                       .Add(Expression.Eq("StartDateTime", startDateTime))
                       .Add(Expression.Eq("RunNumber", runNumber))
                       .Add(Expression.Eq("Revision", revision))
                       .UniqueResult() as OfeMeasurementBase;

            transaction.Commit();

            if (measurement == null) return null;

            // Merge back into main session, in case it has changed since main session was
            // originally loaded
            var mergedMeasurement = (OfeMeasurementBase)mainSession.Merge(measurement);
            return mergedMeasurement;
        }
    }