.NET开发过程中不是程式的无法运行,就是程式的效率慢的同蜗牛在爬; 这种情况在.NET的新手中尤其常见;我不知道为什么,一些介绍.NET开发的书本里引用的例子代码,也对此问题视而不见,尤其让我郁闷的是一些我喜欢的书也出现了同样的问题。
这篇文章不仅对.NET开发者的新手有帮助,同样对哪些有经验,也带来一些启示和参考。354HTML5中文学习网 - HTML5先行者学习网
他们会遇到什么样的问题?354HTML5中文学习网 - HTML5先行者学习网
1. 数据库连接超时354HTML5中文学习网 - HTML5先行者学习网
2. 创建的对象只管用,不管释放354HTML5中文学习网 - HTML5先行者学习网
3. 调试(Debug)模式下编译后,就用于应用环境中了354HTML5中文学习网 - HTML5先行者学习网
4. 实际作业模式分享354HTML5中文学习网 - HTML5先行者学习网
上面的问题就像毒瘤,积累到一定程度就爆发,且影响深远。354HTML5中文学习网 - HTML5先行者学习网
1.数据库连接超时篇354HTML5中文学习网 - HTML5先行者学习网
若要知道数据库连接超时问题,先看下面一段代码:354HTML5中文学习网 - HTML5先行者学习网
[sample-01]354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 Public Shared Function getOEMPN(ByVal psPN As String, ByRef OEMPN As String) As BSResult Dim clsResult As New BSResult Try clsResult.ResultID = -1 Dim dtResult As New DataTable Dim Sql As String = String.Empty Dim clsOraDb As New clsOraClienDb Dim strConn As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString clsOraDb.Open(strConn) ‘这里Open后,后面看不到 clsOraDb.Close Sql = "SELECT SATBMMBRND.OEMPN FRUNO FROM SATBMMBRND WHERE SATBMMBRND.MATNO = :MATNO" Dim params() As racleParameter = {New OracleParameter("MATNO", psPN)} If clsOraDb.FillDataTable(Sql, dtResult, params) = False Then Return clsResult End If If dtResult Is Nothing Then Return clsResult End If If dtResult.Rows.Count > 0 Then OEMPN = dtResult.Rows(0)("FRUNO").ToString() Else OEMPN = "" End If clsResult.ResultID = 1 Return clsResult Catch ex As Exception clsResult.ResultID = -1 Return clsResult End Try End Function354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网对上述代码行的部分解释:354HTML5中文学习网 - HTML5先行者学习网
Dim clsOraDb As New clsOraClienDb:引用数据库连接的类;354HTML5中文学习网 - HTML5先行者学习网
clsOraDb.Open(strConn):打开数据库连接;354HTML5中文学习网 - HTML5先行者学习网
然后,整个函数你再找不到关闭数据库连接的动作,是要等着操作系统来释放吗? 有人就说啦,看起来好像没有什么大不了的,这仅仅是一个函数而已;数据库打开连接,未关闭不会影响到整个应用程式;果真是这样吗?354HTML5中文学习网 - HTML5先行者学习网
让我们谈谈数据库连接的问题,在Oracle数据库里,一般默认的数据库连接数最多也就100多来个,不会超过200个,即使你改变这个连接数;但无论怎样,它的连接数是有限的;不可能无限地供你消耗。354HTML5中文学习网 - HTML5先行者学习网
在Web这个程式里,它不仅不会自动关闭数据库连接,象这样的函数还会每次调用,都会重新用掉一个数据库连接;如果象这样的函数很多的话,你就等着一个错误警告页面弹出来,如Database Connection Timeout…等讯息。354HTML5中文学习网 - HTML5先行者学习网
这还不算什么,更有甚者,尽然在循环语句里写下面的代码如 :354HTML5中文学习网 - HTML5先行者学习网
[sample-02]354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 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 |
354HTML5中文学习网 - HTML5先行者学习网说到这,有人就问啦;我在开发环境下测试一点问题都没有呀?是呀,你是没有问题;我想问的是,你开发环境的测试数据有几笔?354HTML5中文学习网 - HTML5先行者学习网
现在,问题已经知道在哪里,怎么解决?354HTML5中文学习网 - HTML5先行者学习网
针对[sample-01]做如下处理,注意下面代码:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 Public Shared Function getOEMPN(ByVal psPN As String, ByRef OEMPN As String) As BSResult Dim clsResult As New BSResult Try clsResult.ResultID = -1 Dim dtResult As New DataTable Dim Sql As String = String.Empty Dim clsOraDb As New clsOraClienDb Dim strConn As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString clsOraDb.Open(strConn) 注释:这里Open后,后面看不到 clsOraDb.Close Sql = "SELECT SATBMMBRND.OEMPN FRUNO FROM SATBMMBRND WHERE SATBMMBRND.MATNO = :MATNO" Dim params() As racleParameter = {New OracleParameter("MATNO", psPN)} If clsOraDb.FillDataTable(Sql, dtResult, params) = False Then Return clsResult End If If dtResult Is Nothing Then Return clsResult End If If dtResult.Rows.Count > 0 Then OEMPN = dtResult.Rows(0)("FRUNO").ToString() Else OEMPN = "" End If clsResult.ResultID = 1 clsOraDb.Close 注释:后面看到 clsOraDb.Close Return clsResult Catch ex As Exception clsOraDb.Close 注释:程序异常也看到 clsOraDb.Close clsResult.ResultID = -1 Return clsResult Throw ex End Try End Function |
354HTML5中文学习网 - HTML5先行者学习网注意上面的两句代码:clsOraDb.Close和clsOraDb.Close;354HTML5中文学习网 - HTML5先行者学习网
在异常处理的时候,特别提醒两点:354HTML5中文学习网 - HTML5先行者学习网
(1)你的数据库关闭的时候应该是在代码行0028前,而不是后;354HTML5中文学习网 - HTML5先行者学习网
(2)有人不习惯(或者一时疏忽)加上0088行的代码;354HTML5中文学习网 - HTML5先行者学习网
针对[Sample-02]和[sample-03],把打开数据库连接写在所有的循环语句之前,如:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 clsOraDb.Open(strConn) Foreach(DataRow row in tabl.select(“”,”ProductID”) ……………
…………. Next |
354HTML5中文学习网 - HTML5先行者学习网当然还有另外一个做法,就是用Using语句,提交.NET应用的垃圾收集器自动收集;相关的文章很多;这里不再特别赘述。354HTML5中文学习网 - HTML5先行者学习网
2.对象只管创建应用,不管释放篇354HTML5中文学习网 - HTML5先行者学习网
我们继续用[Sample-01]的代码:354HTML5中文学习网 - HTML5先行者学习网
Dim dtResult As New DataTable354HTML5中文学习网 - HTML5先行者学习网
谁会发现它被释放,你不能,我也不能,从来没有被释放过。354HTML5中文学习网 - HTML5先行者学习网
“Dim dtResult As New DataTable”行的代码解释是,要在内存划分一个空间给这个定义的对象dtresult;系统要划分多大的空间呢?呀,我没有研究过(留给那些有心人吧,呵呵。.);但有一点,要在内存划分一个空间,就是要占用内存;那么内存有多大呢,不是无限大吧;也是有限的;所有运行上述代码的最终结果是,系统的执行效率越来越慢;有人就怀疑,我有内存1到2G的,加上虚拟内存就更大;我只能说你的怀疑没错;可是你的应用程序就用这么一只函数吗?我想肯定不是;所以上百只函数的应用执行对内存的消耗可想而知;如果是后台自动运行的程序,及时是一个function,也会让系统崩溃;这只是一个简单的例子,有更复杂的;象这样的对象应用还有:Dataset, Datatable,DataReader,DataAdapter,Datagrid.。等;354HTML5中文学习网 - HTML5先行者学习网
那么怎么解决这些问题呢?354HTML5中文学习网 - HTML5先行者学习网
(1)在Try catch 语句前定义好所用的对象; 如:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 Dim dtResult As New DataTable Dim DR as New DataReader Dim DS as New Dataset Try .. Catch ex As Exception354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网(2)释放的语句如下:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 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 --从内存里清楚该354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网 有人习惯写成下面这样:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 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 Exception354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网这不是也释放了吗?我想问的是,如果程序出现异常,它们会释放吗?我肯定得告诉大家,它们一定不能释放。为了确保程序的稳定运行,我建议大家都来用Try Catch语句。354HTML5中文学习网 - HTML5先行者学习网
(3)绝不建议在循环语句写如下的语句:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 Foreach (DataRow row in tabl.select(“”,”ProductID”) …………… Dim DS new Dataset 记住此乃写代码之大忌; Dim DT new Databable…. …………. Next 还有一种写法 Dim DS new Dataset Dim DT new Databable… Foreach (DataRow row in tabl.select(“”,”ProductID”)354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网 正确的写法是:354HTML5中文学习网 - HTML5先行者学习网
以下为引用的内容:354HTML5中文学习网 - HTML5先行者学习网 Dim DS new Dataset Dim DT new Databable… Try Foreach (DataRow row in tabl.select(“”,”ProductID”) DS=nothing ‘每次使用,都先把内存空间释放出来 DT=nothing ‘每次使用,都先把内存空间释放出来 DS=GetDatase DT=GetDatatable…………… . …………. Next Catch ex As Exception Throw ex Finally DS.dispose DT.dispose End Try354HTML5中文学习网 - HTML5先行者学习网 |
354HTML5中文学习网 - HTML5先行者学习网另外,提醒大家一点,记得用 For Each 语句替代For i=0 to Rowcount-1;这样的效率改善也是明显的;354HTML5中文学习网 - HTML5先行者学习网
3.调试(Debug)模式下编译就用于应用环境中篇354HTML5中文学习网 - HTML5先行者学习网
大家看下面的图片:354HTML5中文学习网 - HTML5先行者学习网
354HTML5中文学习网 - HTML5先行者学习网
有人会留意这个界面吗?有,但一定不多。354HTML5中文学习网 - HTML5先行者学习网
接着,程式开发好(也包括单元测试),然后编译直接分发到应用环境。354HTML5中文学习网 - HTML5先行者学习网
整个过程就结束了;谁也不曾想,这里埋下了一个深深的地雷;据微软的人讲,这样分发的程式到应用环境,你有多少内存恐怕都不够,所以微软建议我们做如下的工作:354HTML5中文学习网 - HTML5先行者学习网
“