The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

解決 LINQ to SQL 針對更新大型物件的效率極差的問題

我有一個頁面是使用 DetailsView 進行資料的新增與更新動作,其中有個圖片欄位在資料庫中的資料格式為 VarBinary(MAX),直接用來儲存圖檔的二進位內容,在新增資料的時候上傳檔案並存入資料庫中,在更新的時候直更新該欄位的內容,不過在更新的時候執行的時間都非常久,即便是上傳 10KB 左右的圖檔,在執行到 db.SubmitChanges(); 時都會執行個 30 秒以上,如果上傳幾 MB 的檔案就要執行好幾分鐘,所以常常會發生 Timeout 的情況。

這個問題大約困擾我將近一個月的問題,因為實在已經嘗試了太多作法(都是用 LINQ to SQL 的方式)都無法改善效能問題,直到今天用 MSN 問一個朋友這個狀況的時候,問題才剛問完自己就突然靈機一動想到了一個解決方法,也就是嘗試將該 VarBinary(MAX) 欄位設定 UpdateCheck="Never" 看看,結果就真的完全解決效能問題了。

有時候真的很奇怪,自己想不通的問題在問別人時通常會將問題重新思考過一遍,進而更了解問題本身。所以人家才會常說:「當你會問題的時候,問題就已經先解決一半」,我非常的感同身受。

首先,先開啟你的 *.dbml 檔,找出這個欄位:

<Column Name="ContentData" Type="System.Data.Linq.Binary" DbType="VarBinary(MAX) NOT NULL" 
        CanBeNull="false" />

然後將該欄位加上 UpdateCheck="Never" 屬性,然後儲存。

<Column Name="ContentData" Type="System.Data.Linq.Binary" DbType="VarBinary(MAX) NOT NULL" 
        CanBeNull="false" UpdateCheck="Never" />

加上這個屬性之後,LINQ to SQL 對這個表格就會採用「閉式並行存取控制(Pessimistic Concurrency Control)」的方式進行更新作業,也就是說當 LINQ to SQL 在更新 Binary 格式的欄位時就不會在去判斷檔案的內容是否有異動,直接將更新的檔案內容直些寫入資料庫。

相關連結