【茶包射手日記】RDLC報表出現記憶體不足錯誤
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運算式"的策略避避風頭吧!