关于非可视控件的动态创建与释放(二层结构)(100分)

  • 主题发起人 主题发起人 listhano
  • 开始时间 开始时间
L

listhano

Unregistered / Unconfirmed
GUEST, unregistred user!
利用ACCESS数据库,用TADOQuery控件,返回数据集。<br>我要问的问题是:当打开少量的TADOQuery数据集,程序运行正常;如果打开多个数据集,运行程序就会出错(可能是正用内存太多的缘故吧)。请问下面的程序怎样做才能关闭TADOQuery数据集(即用完一个,关闭一个)?<br>==============================<br>{***这是数据层的数据集***}<br>unit uClassTab;<br><br>interface<br><br>uses<br> &nbsp;SysUtils,Classes,ADODB;<br><br>type<br> &nbsp;TTab=class(TObject)<br> &nbsp;public<br> &nbsp; &nbsp;CunQry:TADOQuery;<br> &nbsp; &nbsp;procedure AllQry(AllQryName:string);<br> &nbsp; &nbsp;procedure TabShow(ShowName:string);<br> &nbsp;end;<br><br>implementation<br><br><br>procedure &nbsp;TTab.AllQry(AllQryName:string);<br>var<br> &nbsp;cnn:TADOConnection;<br>const<br> &nbsp; &nbsp;strA='Provider=Microsoft.Jet.OLEDB.4.0;Data Source=';<br> &nbsp; &nbsp;strB=';Persist Security Info=False';<br> &nbsp; &nbsp;mdbName='ClimateNMDat.mdb';<br>begin<br> &nbsp;CunQry:=TADOQuery.Create(nil);<br> &nbsp;cnn:=TADOConnection.Create(nil);<br> &nbsp;cnn.ConnectionString:=strA+ExtractFilePath(ParamStr(0))+mdbName+strB;<br> &nbsp;cnn.LoginPrompt:=false;<br> &nbsp;with CunQry do<br> &nbsp;begin<br> &nbsp; &nbsp;Connection:=cnn;<br> &nbsp; &nbsp;Close;<br> &nbsp; &nbsp;SQL.Clear;<br> &nbsp; &nbsp;SQL.Add('select * from '+AllQryName+' order by year');<br> &nbsp; &nbsp;open;<br> &nbsp;end;<br>end;<br><br><br>procedure &nbsp;TTab.TabShow(ShowName:string);<br>begin<br> &nbsp;AllQry(showName);<br>end;<br><br>=========================<br>{***这是界面层应用情况***}<br><br>{***返回的是树状节点值(其目的是为了查找数据库中的数据表。<br>即R0101、R0102、R0103...R1001、R1002、R1003...***)<br><br>function TfrmMain.tvTTreeNode:string;<br>var<br> &nbsp;parent,child:string;<br><br>begin<br> &nbsp; &nbsp;if (tv.Selected.Parent.Index&lt;9) and (tv.Selected.Parent.Index&gt;=0) then<br> &nbsp; &nbsp; &nbsp;parent:='0'+IntToStr(tv.Selected.Parent.Index+1); //tv是TTreeView;<br><br> &nbsp; &nbsp;if tv.Selected.Parent.Index&gt;=9 then<br> &nbsp; &nbsp; &nbsp;parent:=IntToStr(tv.Selected.Parent.Index+1);<br><br> &nbsp; &nbsp;if (tv.Selected.Index&lt;9) and (tv.Selected.Index&gt;=0) then<br> &nbsp; &nbsp; &nbsp;child:='0'+IntToStr(tv.Selected.Index+1);<br><br> &nbsp; &nbsp;if tv.Selected.Index&gt;=9 then<br> &nbsp; &nbsp; &nbsp;child:=IntToStr(tv.Selected.Index+1);<br><br> &nbsp; &nbsp;if (StrToInt(parent)&gt;=0) and (StrToInt(child)&gt;=0) then<br> &nbsp; &nbsp; &nbsp;Result:='R'+parent+child<br> &nbsp; &nbsp; &nbsp;else<br> &nbsp; &nbsp; &nbsp;Result:='R0101';<br>end;<br><br><br>//当改变树状(即TTreeView)焦点(节点)时显示不同的数据集<br>procedure TfrmMain.tvChange(Sender: TObject; Node: TTreeNode);<br>begin<br> &nbsp;tvSelect(tvTTreeNode);<br>end;<br><br>//在dbg(TDBGrid控件)中显示数据集<br>procedure TfrmMain.tvSelect(strName:string);<br>var<br> &nbsp;s:TTab;<br>begin<br> &nbsp;s:=TTab.Create;<br> &nbsp;s.TabShow(stRName); &nbsp; &nbsp;//&lt;----当多次改变树状节点时这里就产生错误(就是找不到数据库中表了 即R****我想这个可能与打开多个数据集有关)<br> &nbsp;ds.DataSet:=s.CunQry; &nbsp;//ds:是TDataSource;<br> &nbsp;dbg.DataSource:=ds; &nbsp; //dbg:是TDBGrid;<br>end;<br>========================<br><br>s.TabShow(stRName); &nbsp; &nbsp;<br>当多次改变树状节点时这里就产生错误(就是找不到数据库中表了 即R****我想这个可能与打开多个数据集有关);我想到释放数据集,在这个过程中<br>procedure &nbsp;TTab.AllQry(AllQryName:string);<br>这样释放数据集?<br>大概是这种结构有问题,请高手给一个合理的结构。<br>谢谢!
 
1、TADOConnection没必要每次都动态创建吧,那样的话,随着你的<br>AllQry的调用次数增多,TADOConnection也很多。一个就行了。<br>2、〉〉运行程序就会出错<br>出什么错?
 
[:(]没看懂楼主的用意
 
to 时报平<br>谢谢!<br>我会采纳你的建议的。
 
to tianlove<br>我的问题就是:<br>我已经动态创建了TADOQuery.<br>怎样才能动态释放它?(就这么简单的问题)<br>谢谢!
 
首先你的这段程序创建的对象都没有有释放,肯定存在严重的内存泄露,个人看法:<br>1、TTab中可以考虑返回_recordset<br> &nbsp; &nbsp; &nbsp;aADO := MyDBUtils.ExecSQLReturnRS(sqlstr); <br> &nbsp; &nbsp; &nbsp;result := aADO.Recordset;<br> &nbsp; &nbsp; &nbsp;if aADO &lt;&gt; nil then FreeAndNil(aADO);<br>2、当改变树状(即TTreeView)焦点(节点)时显示不同的数据集,此过程最好不要写在OnChange事件中,可以试试其它事件<br>3、TTab定义为全局变量<br>var<br> &nbsp;s:TTab;<br>s:=TTab.Create;<br><br>procedure TfrmMain.tvSelect(strName:string);<br>begin<br> &nbsp;s.Recordset := Nil; &nbsp; &nbsp;//Recordset为返回的_Recordset<br> &nbsp;s.TabShow(stRName); &nbsp; &nbsp;<br> &nbsp;ds.AdoQuery.Recordset := s.Recordset; &nbsp;//AdoQuery可以是TAdoQuery <br> &nbsp;dbg.DataSource:=ds; &nbsp; //dbg:是TDBGrid;<br>end;<br><br>下面是我定义的数据操作类中的一个函数,你参考一下<br>function TDBUtils.ExecSQLReturnRS(strSQL: string): TADOQuery;<br>var<br> &nbsp;ReQuery: TADOQuery;<br>begin<br> &nbsp;Result := nil;<br> &nbsp;try<br> &nbsp; &nbsp;if strSql = '' then exit;<br> &nbsp; &nbsp;ReQuery := TADOQuery.Create(nil);<br> &nbsp; &nbsp;ReQuery.Connection := DBConn;<br> &nbsp; &nbsp;ReQuery.SQL.Clear;<br> &nbsp; &nbsp;ReQuery.SQL.Text := strSQL;<br> &nbsp; &nbsp;ReQuery.Active := true;<br> &nbsp; &nbsp;ReQuery.Connection := nil;<br> &nbsp; &nbsp;result := ReQuery;<br> &nbsp;except<br> &nbsp; &nbsp;on E: Exception do<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;raise Exception.Create('在执行SQL语句' + strSQL + '时,出现以下异常:' + E.Message);<br> &nbsp; &nbsp; &nbsp;result := nil;<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>没有实际测试,自己试一下吧。
 
关键问题的所在<br>procedure TfrmMain.tvSelect(strName:string);<br>var<br> &nbsp;s:TTab;<br>begin<br> &nbsp;s:=TTab.Create;---此变量不要用局部变量.然后在创建之前检测有没有创建过.如果有就没必要再创建了<br><br>你每次节点被改变时.都会调用这个过程.一执行这个过程就会创建一个局部的TTab.<br>节点被改变100次还不让机器冒烟
 
to hellfire2008<br>先谢谢你!<br>你给了我很大的提示。<br><br>&gt;&gt;&gt;......此过程最好不要写在OnChange事件中......<br>你认为写在那个事件中比较好?
 
这段程序出现的问题就是:频繁地创建TTab;因此,出现了调用数据集的时候出错为:“未找到数据指定的值”。<br>把TTab改成全局变量一次性地创建,就没有出现上述的错误了!<br>问题得到了解决。<br>谢谢hellfire2008。
 
程序自动创建数据集写在哪个事件都是一样的.主要是资源要分配好.
 
楼主别忘记结贴.(给分啊.哈哈)
 
结贴了!
 
后退
顶部