熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

引以為戒 .NET開發者常犯的錯誤

2013-11-13 10:28:20  來源: .NET編程 

  NET開發過程中不是程式的無法運行就是程式的效率慢的同蝸牛在爬; 這種情況在NET的新手中尤其常見我不知道為什麼一些介紹NET開發的書本裡引用的例子代碼也對此問題視而不見尤其讓我郁悶的是一些我喜歡的書也出現了同樣的問題

  這篇文章不僅對NET開發者的新手有幫助同樣對哪些有經驗也帶來一些啟示和參考

  他們會遇到什麼樣的問題?

   數據庫連接超時

   創建的對象只管用不管釋放

   調試(Debug)模式下編譯後就用於應用環境中了

   實際作業模式分享

  上面的問題就像毒瘤積累到一定程度就爆發且影響深遠  

  數據庫連接超時篇

  若要知道數據庫連接超時問題先看下面一段代碼:

  [sample]



Public Shared Function getOEMPN(ByVal psPN As String ByRef OEMPN As String) As BSResult
Dim clsResult As New BSResult
Try
clsResultResultID =
Dim dtResult As New DataTable
Dim Sql As String = StringEmpty
Dim clsOraDb As New clsOraClienDb
Dim strConn As String = ConfigurationManagerConnectionStrings(ConnectionString)ConnectionString
clsOraDbOpen(strConn)  這裡Open後後面看不到 clsOraDbClose
Sql = SELECT  SATBMMBRNDOEMPN FRUNO FROM SATBMMBRND  WHERE SATBMMBRNDMATNO = :MATNO
Dim params() As racleParameter = {New OracleParameter(MATNO psPN)}
If clsOraDbFillDataTable(Sql dtResult params) = False Then
Return clsResult
End If
If dtResult Is Nothing Then
Return clsResult
End If
If dtResultRowsCount > Then
OEMPN = dtResultRows()(FRUNO)ToString()
Else
OEMPN =
End If
clsResultResultID =
Return clsResult
Catch ex As Exception
clsResultResultID =
Return clsResult
End Try
End Function

  對上述代碼行的部分解釋

  Dim clsOraDb As New clsOraClienDb:引用數據庫連接的類;

  clsOraDbOpen(strConn):打開數據庫連接;

  然後整個函數你再找不到關閉數據庫連接的動作是要等著操作系統來釋放嗎? 有人就說啦看起來好像沒有什麼大不了的這僅僅是一個函數而已;數據庫打開連接未關閉不會影響到整個應用程式;果真是這樣嗎?

  讓我們談談數據庫連接的問題在Oracle數據庫裡一般默認的數據庫連接數最多也就多來個不會超過即使你改變這個連接數但無論怎樣它的連接數是有限的不可能無限地供你消耗

  在Web這個程式裡它不僅不會自動關閉數據庫連接象這樣的函數還會每次調用都會重新用掉一個數據庫連接;如果象這樣的函數很多的話你就等著一個錯誤警告頁面彈出來如Database Connection Timeout…等訊息

  這還不算什麼更有甚者盡然在循環語句裡寫下面的代碼如

  [sample]



  Foreach(DataRow row in tablselect(ProductID)
……………
clsOraDbOpen(strConn)
…………
Next
有人還喜歡玩下面的語句:
[sample]
Foreach(DataRow row in tablselect(ProductID)
Foreach(DataColumn col in lumns)
……………
clsOraDbOpen(strConn)

Next
…………
Next

  說到這有人就問啦我在開發環境下測試一點問題都沒有呀?是呀你是沒有問題我想問的是你開發環境的測試數據有幾筆?

  現在問題已經知道在哪裡怎麼解決?

  針對[sample]做如下處理注意下面代碼:


  Public Shared Function getOEMPN(ByVal psPN As String ByRef OEMPN As String) As BSResult
Dim clsResult As New BSResult
Try
clsResultResultID =
Dim dtResult As New DataTable
Dim Sql As String = StringEmpty
Dim clsOraDb As New clsOraClienDb
Dim strConn As String =


  ConfigurationManagerConnectionStrings(ConnectionString)ConnectionString
clsOraDbOpen(strConn)  注釋這裡Open後後面看不到 clsOraDbClose
Sql = SELECT  SATBMMBRNDOEMPN FRUNO FROM SATBMMBRND  WHERE SATBMMBRNDMATNO = :MATNO
Dim params() As racleParameter = {New OracleParameter(MATNO psPN)}
If clsOraDbFillDataTable(Sql dtResult params) = False Then
Return clsResult
End If
If dtResult Is Nothing Then
Return clsResult
End If
If dtResultRowsCount > Then
OEMPN = dtResultRows()(FRUNO)ToString()
Else
OEMPN =
End If
clsResultResultID =
clsOraDbClose  注釋後面看到 clsOraDbClose
Return clsResult
Catch ex As Exception
clsOraDbClose 注釋程序異常也看到 clsOraDbClose
clsResultResultID =
Return clsResult
Throw ex
End Try
End Function

  注意上面的兩句代碼:clsOraDbClose和clsOraDbClose;

  在異常處理的時候特別提醒兩點

  ()你的數據庫關閉的時候應該是在代碼行而不是後;

  ()有人不習慣(或者一時疏忽)加上行的代碼;

  針對[Sample]和[sample]把打開數據庫連接寫在所有的循環語句之前如:

  

  clsOraDbOpen(strConn)
Foreach(DataRow row in tablselect(ProductID)
……………

…………
Next 

  當然還有另外一個做法就是用Using語句提交NET應用的垃圾收集器自動收集;相關的文章很多這裡不再特別贅述
對象只管創建應用不管釋放篇

  我們繼續用[Sample]的代碼:

  Dim dtResult As New DataTable

  誰會發現它被釋放你不能我也不能從來沒有被釋放過

  Dim dtResult As New DataTable行的代碼解釋是要在內存劃分一個空間給這個定義的對象dtresult;系統要劃分多大的空間呢?呀我沒有研究過(留給那些有心人吧呵呵)但有一點要在內存劃分一個空間就是要占用內存那麼內存有多大呢不是無限大吧也是有限的所有運行上述代碼的最終結果是系統的執行效率越來越慢有人就懷疑我有內存G的加上虛擬內存就更大我只能說你的懷疑沒錯;可是你的應用程序就用這麼一只函數嗎?我想肯定不是所以上百只函數的應用執行對內存的消耗可想而知如果是後台自動運行的程序及時是一個function也會讓系統崩潰這只是一個簡單的例子有更復雜的;象這樣的對象應用還有:Dataset DatatableDataReaderDataAdapterDatagrid等;

  那麼怎麼解決這些問題呢?

  ()在Try catch 語句前定義好所用的對象; 如:




Dim dtResult As New DataTable
Dim DR as New DataReader
Dim DS as New Dataset
Try

Catch ex As Exception
Throw ex
Finally
End Try

  ()釋放的語句如下:




Dim dtResult As New DataTable
Dim DR as New DataReader
Dim DS as New Dataset
Try

……………
Catch ex As Exception
釋放應用的對象
Throw ex
Finally
使用完後釋放應用的對象
dtResultdispose  從內存裡清楚該對象
DRdispose    從內存裡清楚該對象
DSdispose    從內存裡清楚該對象
End Try

  有人習慣寫成下面這樣:




Dim dtResult As New DataTable
Dim DR as New DataReader
Dim DS as New Dataset
Try

使用完後釋放應用的對象
dtResultdispose  從內存裡清楚該對象
DRdispose    從內存裡清楚該對象
DSdispose    從內存裡清楚該對象
Catch ex As Exception
釋放應用的對象
Throw ex
Finally
End Try

  這不是也釋放了嗎?我想問的是如果程序出現異常它們會釋放嗎?我肯定得告訴大家

  它們一定不能釋放為了確保程序的穩定運行我建議大家都來用Try Catch語句

)絕不建議在循環語句寫如下的語句




Foreach (DataRow row in tablselect(ProductID)
……………
Dim DS new Dataset 記住此乃寫代碼之大忌;
Dim DT new Databable…
…………
Next

還有一種寫法
Dim DS new Dataset
Dim DT new Databable…
Foreach (DataRow row in tablselect(ProductID)
DS=GetDatase
DT=GetDatatable……………

…………
Next

  正確的寫法是




Dim DS new Dataset
Dim DT new Databable…
Try
Foreach (DataRow row in tablselect(ProductID)
DS=nothing  每次使用都先把內存空間釋放出來
DT=nothing  每次使用都先把內存空間釋放出來
DS=GetDatase
DT=GetDatatable……………

…………
Next
Catch ex As Exception
Throw ex
Finally
DSdispose
DTdispose
End Try
 
另外提醒大家一點記得用 For Each 語句替代For i= to Rowcount這樣的效率改善也是明顯的;

  調試(Debug)模式下編譯就用於應用環境中篇

  大家看下面的圖片

  .NET編程免費提供,內容來源於互聯網,本文歸原作者所有。

推薦文章
Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.