开发者

Why am I getting this nhibernate NonUniqueObjectException?

The following method queries my database, using a new session. If the query succeeds, it attaches (via "Lock") the result to a "MainSession" that is used to support lazy loading from a databound WinForms grid control.

If the result is already in the MainSession, I get the exception:

NHibernate.NonUniqueObjectException : a different object with the same identifier value was already associated with the session: 1, of entity: BI_OverlordDlsAppCore.开发者_JAVA技巧OfeDlsMeasurement

when I attempt to re-attach, using the Lock method.

This happens even though I evict the result from the MainSession before I attempt to re-attach it.

I've used the same approach when I update a result, and it works fine.

Can anyone explain why this is happening?

How should I go about debugging this problem?

    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;
    }


I resolved the problem after finding this Ayende post on Cross Session Operations.

The solution was to use ISession.Merge to get the detached measurement updated in the main session:

    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;
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜