.NET開發過程中易被忽視的問題

來源:互聯網
上載者:User
在運用Visiol studio.NET 開發Web 應用程式程式中,開發人員常常會遇到一些問題:如我開發好的程式,在開發環境下測試沒問題,怎麼一搬到應用環境下,就會有問題?

在運用Visiol studio.NET 開發Web 應用程式程式中,開發人員常常會遇到一些問題:如我開發好的程式,在開發環境下測試沒問題,怎麼一搬到應用環境下,就會有問題? 不是程式的無法運行,就是程式的效率慢的同蝸牛在爬, 這種情況在.NET的新手中尤其常見。我不知道為什麼,一些介紹.NET開發的書本裡引用的例子代碼,也對此問題視而不見,尤其讓我鬱悶的是一些我喜歡的書,如:<<ADO.NET技術內幕>>,<<ASP.NET2.0進階編程(第4版 )>>,這兩本都是清華大學出版社出版的, 有一本書更糟糕<<Visual Basic.Net 專業項目執行個體開發>>,我建議大家還是不要看了吧,免的浪費時間和精力。
   
    這篇文章不僅對.NET開發人員的新手有協助,同樣對哪些有經驗,也帶來一些啟示和參考。

    他們會遇到什麼樣的問題,我不妨總結給大家:
1. 資料庫連接逾時
2. 建立的對象只管用,不管釋放
3. 調試(Debug)模式下編譯後,就用於應用環境中了
4. 實際作業模式分享
    上面的問題就像毒瘤,積累到一定程度就爆發,且影響深遠。

    一、資料庫連接逾時篇

    若要知道資料庫連接逾時問題,先看下面一段代碼:

[Sample-01]:
Public Shared Function getOEMPN(ByVal psPN As String, ByRef OEMPN As String) As BSResult
0001 Dim clsResult As New BSResult
0002 Try
0003 clsResult.ResultID = -1
0004 Dim dtResult As New DataTable
0005 Dim Sql As String = String.Empty
0006 Dim clsOraDb As New clsOraClienDb
0007 Dim strConn As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
0008 clsOraDb.Open(strConn) ‘這裡Open後,後面看不到 clsOraDb.Close
0009 Sql = "SELECT SATBMMBRND.OEMPN FRUNO FROM SATBMMBRND WHERE SATBMMBRND.MATNO = :MATNO"
0010 Dim params() As OracleParameter = {New OracleParameter("MATNO", psPN)}
0011 If clsOraDb.FillDataTable(Sql, dtResult, params) = False Then
0012 Return clsResult
0013 End If
0014 If dtResult Is Nothing Then
0015 Return clsResult
0016 End If
0017 If dtResult.Rows.Count > 0 Then
0018 OEMPN = dtResult.Rows(0)("FRUNO").ToString()
0019 Else
0020 OEMPN = ""
0021 End If
0022 clsResult.ResultID = 1
0023 Return clsResult
0024 Catch ex As Exception
0025 clsResult.ResultID = -1
0026 Return clsResult
0027 End Try
End Function

    對上述程式碼的部分解釋:
    0006:引用資料庫連接的類;
    0008:開啟資料庫連接;

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

   讓我們談談資料庫連接的問題,在Oracle資料庫裡,一般預設的資料庫連接數最多也就100多來個,不會超過200個,即使你改變這個串連數,但無論怎樣,它的串連數是有限的,不可能無限地供你消耗。
   
    在Web這個程式裡,它不僅不會自動關閉資料庫連接,象這樣的函數還會每次調用,都會重新用掉一個資料庫連接;如果象這樣的函數很多的話,你就等著一個錯誤警告頁面彈出來,如Database Connection Timeout….等訊息。
   
    這還不算什麼,更有甚者,盡然在迴圈語句裡寫下面的代碼如 :

[Sample-02]
Foreach(DataRow row in tabl.select(“”,”ProductID”)
……………
clsOraDb.Open(strConn)
………….
Next
有人還喜歡玩下面的語句:
[Sample-03]
Foreach(DataRow row in tabl.select(“”,”ProductID”)
Foreach(DataColumn col in tbl.columns)
……………
clsOraDb.Open(strConn)

Next
………….
Next

    說到這,有人就問啦,我在開發環境下測試一點問題都沒有呀?是呀,你是沒有問題,我想問的是,你開發環境的測試資料有幾筆?
   
    現在,問題已經知道在哪裡,怎麼解決?

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

Public Shared Function getOEMPN(ByVal psPN As String, ByRef OEMPN As String) As BSResult
0001 Dim clsResult As New BSResult
0002 Try
0003 clsResult.ResultID = -1
0004 Dim dtResult As New DataTable
0005 Dim Sql As String = String.Empty
0006 Dim clsOraDb As New clsOraClienDb
0007 Dim strConn As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
0008 clsOraDb.Open(strConn) 注釋:這裡Open後,後面看不到 clsOraDb.Close
0009 Sql = "SELECT SATBMMBRND.OEMPN FRUNO FROM SATBMMBRND WHERE SATBMMBRND.MATNO = :MATNO"
0010 Dim params() As OracleParameter = {New OracleParameter("MATNO", psPN)}
0011 If clsOraDb.FillDataTable(Sql, dtResult, params) = False Then
0012 Return clsResult
0013 End If
0014 If dtResult Is Nothing Then
0015 Return clsResult
0016 End If
0017 If dtResult.Rows.Count > 0 Then
0018 OEMPN = dtResult.Rows(0)("FRUNO").ToString()
0019 Else
0020 OEMPN = ""
0021 End If
0022 clsResult.ResultID = 1
0088 clsOraDb.Close 注釋:後面看到 clsOraDb.Close
0023 Return clsResult
0024 Catch ex As Exception
0099 clsOraDb.Close 注釋:程式異常也看到 clsOraDb.Close
0025 clsResult.ResultID = -1
0026 Return clsResult
0028 Throw ex
0027 End Try
End Function

    注意上面的兩句代碼:0088行和0099行。

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

    一, 你的資料庫關閉的時候應該是在程式碼0028前,而不是後;

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

    針對[Sample-02]和[sample-03],把開啟資料庫連接寫在所有的迴圈語句之前,如:
 

clsOraDb.Open(strConn)
Foreach(DataRow row in tabl.select(“”,”ProductID”)
……………

………….
Next
 
    當然還有另外一個做法,就是用Using語句,提交.NET應用的垃圾收集器自動收集;相關的文章很多,這裡不再特別贅述。

     二、對象只管建立應用,不管釋放篇
   
    我們繼續用[Sample-01]的代碼,我們現在看0004行的代碼:

0004 Dim dtResult As New DataTable

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

    “0004”行的代碼解釋是,要在記憶體劃分一個空間給這個定義的對象dtresult;系統要劃分多大的空間呢?呀,我沒有研究過(留給那些有心人吧,呵呵..)。但有一點,要在記憶體劃分一個空間,就是要佔用記憶體。那麼記憶體有多大呢,不是無限大吧,也是有限的,所有運行上述代碼的最終結果是,系統的執行效率越來越慢,有人就懷疑,我有記憶體1到2G的,加上虛擬記憶體就更大,我只能說你的懷疑沒錯。可是你的應用程式就用這麼一隻函數嗎?我想肯定不是,所以上百隻函數的應用執行對記憶體的消耗可想而知。如果是後台自動啟動並執行程式,及時是一個function,也會讓系統崩潰。這隻是一個簡單的例子,有更複雜的。像這樣的對象應用還有:Dataset, Datatable,DataReader,DataAdapter,Datagrid..等。

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

   2.1在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
 


2.2釋放的語句如下

Dim dtResult As New DataTable
Dim DR as New DataReader
Dim DS as New Dataset
Try
..
……………..
Catch ex As Exception
--釋放應用的對象
Throw ex
Finally
--使用完後,釋放應用的對象
dtResult.dispose --從記憶體裡清楚該對象
DR.dispose -從記憶體裡清楚該對象
DS.dispose -從記憶體裡清楚該對象
End Try

有人習慣寫成下面這樣:
Dim dtResult As New DataTable
Dim DR as New DataReader
Dim DS as New Dataset
Try
..
‘使用完後,釋放應用的對象
dtResult.dispose ‘從記憶體裡清楚該對象
DR.dispose ‘從記憶體裡清楚該對象
DS.dispose ‘從記憶體裡清楚該對象
Catch ex As Exception
‘釋放應用的對象
Throw ex
Finally
End Try
 


    這不是也釋放了嗎?我想問的是,如果程式出現異常,它們會釋放嗎 ?我肯定得告訴大家,它們一定不能釋放,為了確保程式的穩定運行,我建議大家都來用Try Catch語句。

 



相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

11.11 Big Sale for Cloud

Get Unbeatable Offers with up to 90% Off,Oct.24-Nov.13 (UTC+8)

Get It Now >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。