RDLC比Reporting Service靈活彈性,不需要依賴額外的伺服器,評估起來是很優秀的報表解決方案。

很放心地鼔吹將專案中的報表逐一汰換成RDLC,直到我膝蓋中了一箭最近踩到一顆地雷..

專案有個RDLC查詢報表,大約近萬筆資料,每筆約20個欄位,資料量稍多但還不致令人髮指,執行時卻常常發生記憶體不足(Out of Memory)錯誤! (有時是第一次執行OK,第二次就出現記憶體不足)

檢視報表設計,發現其中用了很多Expression寫法處理資料格式轉換,例如: [=Fields!ColumnA.Value & vbCrLf & Fields!ColumnB.Value]、[=Format(Fields!MyDate.Value, "MMMM")]…。直覺上這些額外運算遍佈在每一筆資料的各欄位中,一旦資料筆數眾多就會被反覆執行,預期會消耗大量記憶體及CPU,懷疑有可能就是導致記憶體不足的元凶。

查了資料,在Microsoft Connect找到兩篇相關回報,證實了此一假設:

其中網友MikeGCompass明確地重現了問題:

I have 2 very simple reports one with an expression and another almost identical but it doesn't contain any report expressions.
ReportBad.rdlc has 1 expression and everytime you generate the PDF it grows in memory, so after a few executes you can have my simple EXE holding on to 1GB or more of memory.
ReportGood.rdlc has 0 expressions and everytime you generate it does not grow in memory.
Thus I conclude using expression columns causes some resources never to be released, even when you dispose the report viewer control.

而在我們的案例中,問題報表在移除Expression後,記憶體不足的狀況確實也消失了。

依此看來,RDLC存在著因Expression導致Memory Leak的Bug,且到VS2010的版本為止尚未解決。目前較可行的解決之道,是在RDLC中避用Expression寫法,例如: 在SQL查詢語法中就預先做轉換,或是先將資料匯入DataTable再進行"後製",會造成些許不便,但尚在可接受範圍之內,在Bug被修復前,就採取"RDLC中儘可能避免使用Expression運算式"的策略避避風頭吧!


Comments

# by Karl Lee

請問如在asp.net MVC 3中,能否使用report viewer ? 我現在只能在controller中,先把rdlc export 成excel 或者pdf, 再以attachment 方式送到client side 。

# by Jeffrey

to Karl Lee, Report Viewer是個WebForm Control,需依賴ViewState才能運作,而ASP.NET MVC中已不再有ViewState的概念,如你說的,看起來直接輸出PDF、Excel等內容是大家在MVC中應用RDLC的解法。不過我想微軟未來應會推出MVC可用的Report Viewer。

# by 佳佳

請問SSRS匯出EXCEL可匯出公式嗎?

# by Jeffrey

to 佳佳,依我所知SSRS的匯出的Excel是數字等資料的傾印結果,應無法在其中另行嵌入公式。如真有需求,可考量用NPOI讀取Excel檔案再加工。

# by Michael Chen

關於 rdlc 的 OutOfMemory bug 因為已經寫好太多張報表(約 500支程式), 所以想請教 當發生 OutOfMemory 後, 有沒有辦法 Release Memory ? 我們公司的問題是, 我們自己有寫一支 AP Server, 不定期會發生 AP Server 當掉的情況, 我們判斷可能跟您這篇 blog 有關, 所以特來請教, 謝謝!

# by Jeffrey

to Michael Chen, 如果記憶體的異常消耗是因為Memory Leak引起,意味著無法使用正常管道回收,那麼除了重啟AppPool Process或IISRESET外,似乎沒有其他好的解決方式,這也是我目前使用的做法。

# by Lydia Tsai

關於RDLC first time load 請問,使用RDLC開發報表,似乎第一次執行都會較慢,但第二次就快很多,差約3-4秒,不知你有遇過此問題嗎?或是有其他建議方向?謝謝!

# by Jeffrey

to Lydia Tsai, ASP.NET程式第一次執行前需要即時編譯,這算是ASP.NET網站的特性,但有些IIS技巧可以改善,請參考: http://www.dotblogs.com.tw/franma/archive/2014/04/23/144845.aspx

# by Phil

請問RS可以不和SQL Server裝在同一台機器嗎? 因為我們發現RS和SQL很佔記憶體。 謝謝

# by Jeffrey

to Phil, Reporting Server跟SQL不用裝在同一台。但我推薦改用RDLC,只要有ASP.NET網站就可以跑,完全不需要Report Server,就不用煩惱要裝在哪裡,資料又可任意組裝加工,彈性無窮,真心推薦。

Post a comment