2012-11-12 43 views
0

運行使用實體框架5 .NET 4.5與SQL Server 2012.我有一個功能,從第三方源下載大量數據並解析它進入我的數據庫。它下載,解析到我的實體並以2500個記錄的批次向我的db插入/更新。數據庫表無響應,而插入/更新使用實體框架W/SqlBulkCopy

爲了插入/更新我的數據庫,我正在使用SqlBulkCopy類。當它插入/更新我的數據庫時,它插入/更新的表似乎部分無響應。如果我從SSMS運行一個簡單的選擇查詢,它將拉出一些記錄,然後掛起,直到應用程序完成大容量插入/更新。我的數據庫中的這些數據通過WCF服務提供給多個源,並且如果我嘗試在其中一個源加載數據,則由於數據庫未響應數據而超時。一旦插入/更新完成,WCF服務和SSMS查詢都將繼續正常運行。

我認爲這可能是由於SqlBulkCopy,所以我刪除了該類的使用,只是調用了一個context.SaveChanges(),它產生完全相同的結果。然後我運行了一個測試,將EF完全從圖片中刪除,並使用了經典的ADO.NET(沒有SqlBulkCopy),並且一切都很好。我把SqlBulkCopy插回去了,把EF留下了,再次,表似乎被鎖定,直到完成。

所以我假設這裏的罪魁禍首是EF和SqlBulkCopy。關於如何解決這個問題並仍然使用EF和SqlBulkCopy的任何想法?或者可能導致這種情況發生的原因?

我不認爲我的代碼的例子在這裏是必要的,但如果你想看,請讓我知道。提前致謝。

+0

我認爲這是一個服務器設置。我在我的客戶使用的共享託管服務器上有此問題。在數據傳輸過程中,我甚至可以不用「SELECT TOP 1」。它只會坐在那裏「執行查詢..」30-45分鐘。 –

+0

這不是共享服務器。數據庫運行在由2個具有中央存儲節點組成的sql羣集中。一次只能運行一個,另一個是故障轉移。該應用程序託管在2個其他負載均衡的專用Web服務器上。長時間的「執行查詢」是我通過SSMS體驗的同一件事。如果你知道這可能是什麼設置,這可能會有所幫助。 – Ricketts

回答

1

我在想這是因爲交易。當您使用SqlBukCopy或context.SaveChanges()時,插入會發生在事務中。當你用傳統的ADO.NET替換代碼時,你是否將插入包裝在事務中,還是讓每個插入發生在它自己的隱式事務中?

當事務處於掛起狀態時,它會鎖定正在更新的部分表。如果它插入了足夠的數據,它可能會鎖定表格或整個表格中的大量頁面(這稱爲lock escalation)。

解決此問題的最佳方法是將更新拆分爲更小的塊。還有其他一些選擇(例如讀取未提交的數據等),但這些選項有明顯的缺點,通常應避免。

+0

我已閱讀有關SqlBulkInsert默認會執行的行鎖定。我也可以理解它是在交易中完成的。但是,如果是這種情況,那麼select查詢是否仍然執行,但排除涉及事務的記錄?至於ADO.NET,我沒有將它們包裝在一個事務中,而是在它們自己的隱式事務中執行。我會嘗試將它分成小塊(也許是500?),我也會嘗試將ADO.NET版本包裝到事務中,並從中看到結果。感謝您的意見。 – Ricketts

+0

select查詢不能排除涉及事務的記錄;這違反了數據完整性關係數據庫堅持的一些基本原則。換句話說,如果選擇需要讀取被鎖定的數據,它必須等待。此外,即使SqlBulkInsert在默認情況下執行了行鎖定,但在插入足夠的數據時,該鎖可以升級爲頁面或表鎖。 –

+0

好的,我跑了一些測試。我嘗試只使用ADO.NET和一個事務插入50,000條記錄。在comm.ExecuteNonQuery()中,這是一直需要的,該表繼續正常響應。我在ExecuteNonQuery()函數下的transaction.Commit()行上放置了一個斷點,並且當斷點擊中提交行時,該表退出響應,因爲它與EF&SqlBulkCopy一樣。當我走了過去,沒有時間延遲,桌子又開始正常響應了。所以看起來確實是交易的承諾。 – Ricketts

相關問題