2011-06-04 12 views
8

獲取「不允許新的事務,因爲會話中有其他線程正在運行」。由於會話中還有其他線程正在運行,所以不允許新的事務

它與foreach循環或任何人通常與此消息相關的問題無關。

我在整個請求中使用帶有repositoy模式和公共上下文的EF4。發生某些事情時,無法確定究竟是什麼,只要我嘗試通過上下文保存與請求相關的更改,我就會收到此消息,並且只有在我回收應用程序池後纔會消失。

我關閉了連接嗎?我怎麼知道?我是否爲每個請求使用新的上下文?是。

發生了什麼事?有沒有解決辦法?

編輯:(上下文工廠)

private static Dictionary<string, CoinEntities> _instances; 

    public static CoinEntities DefaultInstance 
    { 
     get 
     { 
      if (HttpContext.Current == null) 
      { //todo: mock instead. testing. 
       if (!Instances.ContainsKey("_TEST")) 
        Instances["_TEST"] = new CoinEntities(); 
       return Instances["_TEST"]; 
      } 

      if (!Instances.ContainsKey("_DEFAULT")) 
       Instances["_DEFAULT"] = new CoinEntities(); 

      return Instances["_DEFAULT"]; 
     } 
    } 
+0

杜佩到http://stackoverflow.com/questions/2113498/sqlexception- from-entity-framework-new-transaction-is-not-allowed-because -other – Korayem 2012-09-20 12:50:28

回答

16

我不認爲這只是未處理的上下文的問題(上下文不保留已打開的事務 - 您會因爲未提交的更改而看到它)。如果你有這個問題,你很可能不會對每個請求使用新的上下文實例,或者你對共享上下文實例(=一個連接)有一些多線程/異步處理。這個例外說多線程(可能是多個處理過的請求)試圖在同一個連接上使用他們自己的事務 - 這是不可能的。

角落案例可以手動處理提供給上下文的連接,但我想你會提及它,如果你使用它。

編輯:

你的工廠沒有每個請求的情況下提供 - 它提供了一個上下文的所有要求!該靜態字典在所有請求之間共享,因此第一個創建實例並將其存儲在_DEFAULT密鑰下,所有其他請求將使用它。

+0

我所有的回購都是在控制器構造函數中啓動的。據我所知,我沒有任何多線程處理,除非我不知情地介紹了一些東西。除了我非常嚴格控制的一個地方之外,沒有手動連接處理,很少被稱爲 - 我確定它沒有關係。所以,我不知道這是否會讓我失望。 – Martin 2011-06-04 21:54:54

+0

您是否手動處理事務('TransactionScope')?這些示波器是否正確完成/處置? – 2011-06-04 21:59:15

+0

好吧,回購是從靜態工廠方法提供的上下文,但我仍然不知道它如何能夠在請求之間生存。對?多年來一直如此。 – Martin 2011-06-04 21:59:47

1

當您的請求完成你不處置的環境。您可以通過應用使用塊作出處置的背景下...

using (var context = new MyContext()) 
{ 
    // Do Db stuff and SaveChanges, etc. 
} 
// context gets disposed automatically here 

...或明確:

context.Dispose(); 

(這是我的理論根據您的輸入到目前爲止。)

+0

請求結束後不會處理上下文嗎?使用MCV。這從來沒有發生過,就是這樣。開發一年後開始發生。無法真正追蹤到任何事情。 – Martin 2011-06-04 16:04:21

+0

@Martin:它不會自動處理。你必須以某種方式編程它。 MVC中的控制器有一個虛擬的'Dispose'方法可以覆蓋。處理請求後,將自動調用此方法。這是一個放置上下文的好地方(如果您在控制器的構造函數中創建上下文)。 – Slauma 2011-06-04 17:28:47

+0

超級。我會去做。 – Martin 2011-06-04 17:31:05

4

它與新的EF4隱式事務有關。

這意味着當您打開一個AsEnumerable()或ObjectQuery實體請求時,您處於一個事務中,避開它的一種方法是將AsArray()查詢,然後您不再處於事務中。另一種可能是通過樂觀鎖定關閉交易?但我無法找到它。

這是我的解決方案

RespondableSites = model.HyperTextLinkEntitySets.OfType<Site>() 
         .Where(x => 
         (
          x.moz_RESPONSEDATA != null 
          && x.RowState.IndexOf("a=") < 0)) 
         ).ToArray(); 


foreach (var siteObj in RespondableSites) 
{ 
    using (var context = new brandshieldDBEntities()) 
    { 
     ParseResponseData(siteObj); 
     model.SaveChanges(); 
    } 
} 

和它的作品,它是緩慢的,但它的工作原理..

檢查這裏: SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session

+0

感謝您的解釋。這解決了我的問題! – ra00l 2013-04-05 07:48:20

0

試試這個代碼。它可能有幫助。在這段代碼中,我把所有的ID從數據庫,並命名爲ctx數據庫上下文的新對象在它們之間迭代:

var listOfCourseId = db.Courses.Where(c => c.CourseStatus == 1).Select(c => c.CourseId); 
     using (var ctx = new UniversityDbContext()) 
     { 
      foreach (var acourseId in listOfCourseId) 
      { 
       Course selectedCors = new Course(); 
       selectedCors = ctx.Courses.Where(id => id.CourseId == acourseId).Single(); //hence use ctx.tableName instead of db.tableName 
       selectedCors.CourseStatus = 0; 
       ctx.Entry(selectedCors).State = EntityState.Modified; 
       ctx.SaveChanges(); 
      } 
     } 
相關問題