2011-09-30 160 views
1

以下方法使用新會話查詢我的數據庫。如果查詢成功,它將(通過「鎖定」)結果附加到用於支持從數據綁定WinForms網格控件延遲加載的「MainSession」。爲什麼我得到這個nhibernate NonUniqueObjectException?

如果結果是已經在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; 
    } 
+0

我不知道預期的行爲,但'measurement'對象,你正試圖從'mainSession'驅逐不是該會話持有的同一個對象,所以我想知道它是否應該以這種方式工作。 – Jay

回答

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