2010-04-10 80 views
2

我想在執行潛在冗長的數據庫操作時向用戶顯示詳細的進度信息。特別是,當插入/更新數百KB或MB數量級的數據時。如何在使用ADO.NET時最好地顯示進度信息?

目前,我正在使用內存中的DataTables和DataRows,然後通過TableAdapter.Update調用與數據庫同步。這工作正常,很花哨,但單一的電話幾乎沒有機會收集任何種類的進度信息以顯示給用戶。我不知道有多少數據通過網絡傳輸到遠程數據庫或其進程。基本上,我所知道的是當Update返回並假定完成時(禁止任何錯誤或異常)。但這意味着我能展示的只有0%,然後是暫停,然後是100%。

我可以統計行數,甚至到目前爲止還有多少實際上是修改或添加的,我甚至可能會根據每列的數據類型計算每個DataRow的估計大小,對於值類型使用sizeof像int和檢查字符串或字節數組等東西的長度。這樣,我可以在更新之前確定估計的總傳輸大小,但是一旦TableAdapter調用Update,我仍然無法獲得任何進度信息。

我堅持使用不確定的進度條或鼠標等待光標?我是否需要從根本上改變我們的數據訪問層才能夠連接到這種信息?即使我無法把它傳遞給精確的KB(例如web瀏覽器文件下載進度條),我是否至少可以知道每個DataRow/DataTable何時完成?

如何最好地展示這種使用ADO.NET的進度信息?

回答

1

對於SELECT部分,有一個半解決方案,它首先發出COUNT查詢以獲得您希望接收的行數。如果COUNT查詢可以非常快地返回一個結果(即在幾分之一秒內),那麼這是唯一可行的 - 另一方面,如果運行需要幾秒鐘,那麼查詢執行本身(而不是結果枚舉)可能會比數據傳輸花費更長的時間,在這種情況下,根本不值得嘗試顯示一個獨立的進度條。

至於UPDATEINSERT - 不,沒有任何簡單的解決方案,特別是使用TableAdapter。如果要發送大量數據,則可能需要考慮使用SqlBulkCopy類上載到登臺表,然後在服務器上執行實際更新。該類提供NotifyAfter屬性以及SqlRowsCopied事件,該事件可以給出當前進度的合理近似值(由於它們在內存中,因此您已知道此情況下的總行數)。

這當然需要對當前的TableAdapter實現進行重大更改,但.NET中的類型化數據集系統實際上並未設計爲處理除LAN連接之外的任何大小的記錄集。

我認爲大多數人只會選擇使用選框進度條。用戶期望如此;即使您可以準確預測行數和數據傳輸速率,但您仍然不知道查詢實際執行需要多長時間,特別是在服務器負載較重的情況下,並且可以說提供的更糟糕的是要提供bad estimates比沒有估計。

如果有一個現實的機會,查詢(或更新)本身需要很長時間才能在服務器上運行,不計算任何時間上傳/下載記錄,那麼我肯定會使用一個選取框進度條。否則...祝你好運。

+0

不使用SqlBulkCopy嘗試插入所有行作爲新行?我的意思是,如果調用WriteToServer時傳遞給它的DataTable有一些RowState == Modified的行,那麼它是更新這些行還是插入新的PK?如果KeepIdentity已啓用,該怎麼辦?如果它試圖插入和PK是相同的,那麼我想它會拋出一個SqlException。也許這值得另外一個問題。 MSDN文檔不具體... – 2010-04-11 07:34:24

+0

沒關係。當MSDN文檔失敗時,MSDN博客即可解救。 http://blogs.msdn.com/irenak/archive/2006/02/10/529553.aspx – 2010-04-11 07:41:35

+0

@Yadyn:'SqlBulkCopy'封裝了一個不更新的批量插入操作,這就是你需要使用臨時存儲的原因表。一般來說,如果讓'DataSet'和相關的類與框架中的其他任何數據類一起工作,你就不會有太多的運氣 - 你可能不得不開始擺脫這些,因爲它們是基於將整個記錄集加載到內存而不是從TDS流式傳輸的概念。 – Aaronaught 2010-04-11 15:21:04

0

正如Aaronaught所說--SqlBulkCopy和NotifyAfter應該能夠工作(儘管它對我有用)。

,我不認爲這將是「顯著變化」到當前的DAL實現...

相關問題