2013-08-06 16 views
4

我收到以下錯誤試圖保存在實體框架的變化 -實體框架 - 「新的事物是不允許的,因爲有在會話中運行其他線程」

System.Data.SqlClient.SqlException:新事務不被允許,因爲會話中還有其他線程正在運行。

我見過各種各樣的回答這個問題,但我似乎無法得到其中的任何工作,基本上我保存在我的倉庫內交易的大量項目,我通過幾個項目具有循環刪除它們並編寫審計記錄。

我見過的所有其他答案(例如Mark Staffords Answer)都建議聲明一個顯式事務(我有)或者在完成循環後只調用保存更改(由於目前的審計方式,這不是一個選項 - 需要審計ID來編寫審計詳細記錄)。

每當「的SaveChanges」被稱爲刪除方法內部引發的錯誤,見下文 -

public virtual void Save(DoseReturn oldDoseReturn) 
{ 
    // Get the datetime when the save started 
    DateTime saveStartTime = DateTime.Now; 
    Dictionary<string, object> oldValues = new Dictionary<string, object>(); 
    Dictionary<string, object> newValues = new Dictionary<string, object>(); 

    // Get the object context and open a new transaction 
    ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext; 
    objectContext.Connection.Open(); 
    DbTransaction transaction = objectContext.Connection.BeginTransaction(); 

    // Use the transaction for all updates 
    using (transaction) 
    { 
     if (oldDoseReturn != null) 
     { 
       IDoseReturnStatusRepository statusRepository = new DoseReturnStatusRepository(); 
       var list = statusRepository.AsQueryable().Where(x => x.DoseReturnID == oldDoseReturn.DoseReturnID); 

       foreach (var item in list) 
       { 
        statusRepository.Delete(item, objectRetrievedDateTime, objectContext, saveStartTime, out oldValues, out newValues); 
       } 

       context.SaveChanges(); 

       // Get the relevant repository 
       IDoseReturnsRepository repository = new DoseReturnsRepository(); 

       // audit and delete the object 
       repository.Delete(oldDoseReturn, objectRetrievedDateTime, objectContext, saveStartTime, out oldValues, out newValues); 

       context.SaveChanges(); 
     } 
    } 

    try 
    { 
     // Conduct a final save, then commit the transaction 
     context.SaveChanges(); 
     transaction.Commit(); 
    } 
    catch (Exception ex) 
    { 
     // An error has occurred, rollback the transaction and close the connection, then present the error 
     transaction.Rollback(); 
     objectContext.Connection.Close(); 
     throw ex; 
    } 
    // Close the connection 
    objectContext.Connection.Close(); 
} 

public virtual void Delete(T entity, DateTime? objectRetrievedDateTime, ObjectContext objectContext, DateTime saveStartTime, out Dictionary<string, object> oldValues, out Dictionary<string, object> newValues) 
    { 
     oldValues = new Dictionary<string, object>(); 
     newValues = new Dictionary<string, object>(); 

     if (entity == null) 
     { 
      throw new ArgumentException("Cannot update a null entity."); 
     } 

     string entityName = entity.GetType().Name; 

     if (!objectRetrievedDateTime.HasValue || !this.AuditsAfterRetieval(objectRetrievedDateTime, entityName, entity, saveStartTime)) 
     { 
      this.DeletedEntityAudit(entity, out oldValues, out newValues); 

      context.Entry(entity).State = System.Data.EntityState.Deleted; 
      this.context.Set<T>().Remove(entity); 
      this.Audit(entity, entityName, "Delete", oldValues, newValues, true); 
      this.context.SaveChanges(); 
     } 
     else 
     { 
      throw new Exception("Object cannot be saved as it has been amended in another thread"); 
     } 
    } 

回答

21

這可能是因爲你試圖保存更改時列舉的結果。

嘗試改變這一行:

var list = statusRepository.AsQueryable() 
       .Where(x => x.DoseReturnID == oldDoseReturn.DoseReturnID); 

到:

var list = statusRepository.AsQueryable() 
       .Where(x => x.DoseReturnID == oldDoseReturn.DoseReturnID) 
       .ToList(); 

作爲一個側面說明調用.SaveChanges()一個循環中通常不是一個好主意,因爲它是在一般的昂貴的操作(會談到數據庫)。

+0

嗨,感謝您的迴應,我現在就試試。 – user1948635

+0

明智,已經改變它,因此它循環刪除所需的項目並存儲一個ID列表,然後在第二個循環中它通過ID獲取並調用刪除功能。 Thankyou再次在昨天下午的大部分時間裏都陷入了僵局。 – user1948635

相關問題