蓝天国度 發表於 2022-4-18 22:13:00

delphi 新版内存表 FDMemTable

<div id="content_views" class="htmledit_views">
<p>c++builder XE</p>
<p>官方demo最全60多个</p>
<p>http://community.embarcadero.com/blogs?view=entry&amp;id=8761</p>
<p>&nbsp;</p>
<p>&nbsp;FireDAC.Comp.Client</p>
<p>&nbsp;</p>
<p>用好FDMemTable代替之前的ClientDataSet,以前ClientDataSet内存表转换太繁琐了步骤。</p>
<p>&nbsp;TClientDataSet *cds = new TClientDataSet(this);<br> &nbsp;&nbsp;DataSetProvider1-&gt;DataSet = dm-&gt;ADOQueryPub;<br> &nbsp;&nbsp;cds-&gt;ProviderName = "DataSetProvider1";<br> &nbsp;&nbsp;cds-&gt;Open();</p>
<p>&nbsp;</p>
<p>c++智能指针</p>
<p>&nbsp;#include &lt;memory&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//For STL auto_ptr class</p>
<p>std::auto_ptr&lt;TFDMemTable&gt; table (new TFDMemTable(NULL));</p>
<p>&nbsp;</p>
<p>一句就可以了</p>
<p>FDMemTable1-&gt;CopyDataSet(dm-&gt;ADOQueryPub,
TFDCopyDataSetOptions() &lt;&lt; coStructure &lt;&lt; coRestart &lt;&lt;
coAppend);</p>
<p>&nbsp;</p>
<p>多用FDMemTable,不再用ClientDataSet\DataSetProvider1做转换了</p>
<p>FDMemTable2-&gt;Data = FDMemTable1-&gt;Data;</p>
<p>FDMemTable2-&gt;CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() &lt;&lt; coStructure &lt;&lt; coRestart &lt;&lt; coAppend);</p>
<p>&nbsp;</p>
<p><strong>建立缓存表</strong></p>
<pre>FDMemTable1.Close();
FDMemTable1.FieldDefs.Clear();
FDMemTable1.FieldDefs.Add('ID', ftInteger, 0, True);
FDMemTable1.FieldDefs.Add('Name', ftString, 20, false);
FDMemTable1.CreateDataSet();
FDMemTable1.AppendRecord();
FDMemTable1.AppendRecord();
FDMemTable1.AppendRecord();
</pre>
<p><strong>0)FDMemTable1.SourceView遍历各行数据,取任意行数据无需Next移动指针了。TFDDatSView</strong></p>
<p>&nbsp;for (int i = 0; i &lt; FDMemTable1-&gt;SourceView-&gt;Rows-&gt;Count; i++)<br> &nbsp;{undefined<br> &nbsp;&nbsp;Caption = FDMemTable1-&gt;SourceView-&gt;Rows-&gt;ItemsI-&gt;GetData(1);<br> &nbsp;}</p>
<p>FDMemTable1-&gt;SourceView-&gt;Rows-&gt;ItemsI-&gt;GetData("fieldName");//取指定行指定字段名的值<br> &nbsp;}</p>
<p><strong>9行7列的值。</strong></p>
<p>&nbsp;FDMemTable1.Data.DataView.Rows.ItemsI.ValueI;</p>
<p>&nbsp;FDMemTable1.Table.Rows.ValueI</p>
<p>&nbsp;Caption = FDMemTable1-&gt;SourceView-&gt;Rows-&gt;Count;//过滤后1条<br> &nbsp;Caption = FDMemTable1-&gt;Table-&gt;Rows-&gt;Count;//过滤无效,全部记录3条</p>
<p>&nbsp;</p>
<pre>iMax := 0;
for i := 0 to FDQuery1.SourceView.Rows.Count - 1 do
if FDQuery1.SourceView.Rows.GetData('id', @iVal) and (iVal &gt; iMax) then
    iMax := iVal</pre>
<p>&nbsp;</p>
<p><strong>数据集拷贝,复制数据集,合并数据集</strong></p>
<p>&nbsp;FDMemTable1-&gt;Filter = "id=102";<br> &nbsp;FDMemTable1-&gt;Filtered = true;</p>
<p>FDMemTable1只有1条记录</p>
<p><strong>&nbsp;1)Data</strong></p>
<p>FDMemTable2-&gt;Data = FDMemTable1-&gt;Data;</p>
<p>&nbsp;</p>
<p>FDQuery-&gt;Open("select * from tt");</p>
<p>FDMemTable2-&gt;Data = FDQuery-&gt;Data;</p>
<p>&nbsp;</p>
<p>FDMemTable2是全部记录,有3条记录。</p>
<p>FDMemTable1-&gt;Delete();后的记录不在Data里。</p>
<p><strong>&nbsp;2)CopyDataSet</strong></p>
<p><strong>带结构拷贝</strong></p>
<p>FDMemTable2-&gt;CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() &lt;&lt; coStructure &lt;&lt; coRestart &lt;&lt; coAppend);</p>
<p>&nbsp;FDMemTable2-&gt;CommitUpdates();</p>
<p>缓存更新用到changeCount,所以copy完后加上CommitUpdates</p>
<p>&nbsp;</p>
<p><strong>不带结构,仅拷贝数据,字段个数可以不一致,字段数以目标数据集FDMemTable2为标准。</strong></p>
<p>FDMemTable2-&gt;CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() &lt;&lt;&nbsp; coRestart &lt;&lt; coAppend);</p>
<p>//第二个参数默认是coRestart &lt;&lt; coAppend,所以下面就更简单了。</p>
<p>FDMemTable2-&gt;CopyDataSet(FDMemTable1);</p>
<p>FDMemTable2只有1条记录</p>
<p><strong>&nbsp;3)CopyRecord\CopyField</strong></p>
<p>copy the current record field values .Only One Record</p>
<p>&nbsp;&nbsp;FDMemTable2-&gt;CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() &lt;&lt; coStructure);<br> &nbsp;FDMemTable2-&gt;Edit();<br> &nbsp;FDMemTable2-&gt;CopyRecord(FDMemTable1);</p>
<p><strong>&nbsp;4)CloneCursor</strong></p>
<p>All Record, ignore filter</p>
<p>CloneCursor,数据共享,一个修改,另一个也修改了,但是FDMemTable1-&gt;Close之后FDMemTable2还正常显示。</p>
<p>FDMemTable2-&gt;CloneCursor( FDMemTable1);</p>
<p>&nbsp;2016.3.4 test 不能排序,FDMemTable2-&gt;IndexFieldNames = "ID";不起作用,所以尽量不建议用这个方式。</p>
<p><strong>5)AtrachTable</strong></p>
<p>All Record,ignore filter,TFDDatSTable</p>
<p>&nbsp;FDMemTable2-&gt;AttachTable(FDMemTable1-&gt;Table, NULL);</p>
<p>//or</p>
<p>//FDMemTable2-&gt;AttachTable(FDMemTable1-&gt;Table,FDMemTable1-&gt;View);<br> &nbsp;FDMemTable2-&gt;Open();</p>
<p><strong>6)FilteredData</strong></p>
<pre name="code">FDQuery1.Filter := 'upper(name) like ''D%''';
FDQuery1.Filtered := True;
<em>// copy to FDMemTable1 all FDQuery1 visible (where name starts from D) records</em>
FDMemTable1.Data := FDQuery1.FilteredData;

RecordCount是过滤后的记录数。过滤前有100行,过滤后有5行,那么RecordCount就是5
FDQuery1-&gt;Data是100行,FilteredData是5行的数据
<strong>7)XMLData
</strong>All Record ignore filter
&nbsp;Memo1-&gt;Text = FDMemTable1-&gt;XMLData;
&nbsp;FDMemTable2-&gt;XMLData = Memo1-&gt;Text;

FDMemTable1-&gt;ChangeCount,
通过Data赋值,默认全部记录都是修改过的,也就是ChangeCount=RecordCount,有100条记录,获取ChangeCount属性就是100.这样合适还是不合适呢?
FDMemTable1-&gt;Data = FDQuery-&gt;Data;
FDMemTable1-&gt;CancelUpdates();或者FDMemTable1-&gt;CommitUpdates();
加上CancelUpdates这句话,ChangeCount就正常了!!反应真实的修改记录数。
Append的记录需要把属性CachedUpdates设为true,ChangeCount就正确了。
<strong>8)Delta
IFDDataSetReference类型</strong>
FDMemTable2-&gt;Delta= FDMemTable1-&gt;Delta;

ADMemTable1.FilterChanges := ;
ADMemTable1.Data := ADQuery1.Delta;

<strong>9)查看删除过的记录UpdateStatus</strong>

<strong>FDMemTable想要找到并显示删除的记录</strong>
   FDMemTable1-&gt;Delete();
&nbsp;&nbsp;&nbsp;FDMemTable2-&gt;FilterChanges &lt;&lt; Firedac::Comp::Dataset::rtDeleted;
&nbsp;&nbsp;&nbsp;FDMemTable1-&gt;Data = FDMemTable1-&gt;Data;
while (!FDMemTable1.eof)
{
if( table-&gt;UpdateStatus() == usDeleted)
...
}
默认是不显示删除过的记录的,FilterChanges不包括rtDeleted属性。
<strong>10)分页及加载全部页</strong>
FetchOptions的Mode默认是fmOnDemand表示分页,每页50,改为fmAll表示全部记录。
分页TFDFetchOptions.RowsetSize
FetchNext
FetchAll
FetchOptions.RecordCountMode property

FDQuery1.Open;
FDQuery1.FetchAll;//必须加这一句,否则数据集不全。
FDMemTable1.Data := FDQuery1.Data;
用了grideh,为何导致分页不灵了???全部记录出来了?field设置了ftsum导致,不设置每次就50行记录。

LocateEx
</pre>
<p>11)增强的Locate功能LocateEx、LookupEx函数</p>
<pre>lxoCheckOnly &nbsp;If included, then LocateEx does not:</pre>
<pre>Change the current position. Fire BeforeScroll / AfterScroll events. Finish editing mode
不改变位置和编辑状态的搜索,强大!
<strong>12)刷新数据集</strong>
query1.Refresh();

<strong>13)只读字段</strong>
select'' as temp,flag=0,sql返回的虚拟字段,以前clientDataSet可以修改,FDMemTable里不能改了。
ClientDataSet1-&gt;FieldByName("flag")-&gt;AsString="1";
但是FDMemTable不能改了。怎么办?以前的这种虚拟字段的方式挺好用啊。
解决办法:设置属性TFDMemTable.UpdateOptions.CheckReadonly=true

<strong>14)主从表关系</strong></pre>
<pre name="code" class="set-code-hide">第一步:
fdqueryDetail.MasterSource := DataSource1;
第二步:
fdqueryDetail.MasterFields := 'OrderNo'; { 多个字段时用分号隔开 }
或者
fdqueryDetail.sql.text='select&nbsp;*&nbsp;from&nbsp;OrderDetail&nbsp;where&nbsp;OrderMasterKey=:OrderMasterKey';

两个FDMemTable做主从怎么不起作用呢?

<strong>15)过滤数据FilterChanges</strong>
只显示修改后的数据
ClientDataSet1-&gt;FilterChanges = TFDUpdateRecordTypes() &lt;&lt; Firedac::Comp::Dataset::rtModified;

ClientDatSet用Grideh可以排序,添加EhLibCDS.pas文件即可。
TFDMemTable添加EhLibFireDAC.pas怎么不起不能排序,报错TFDMemTable is not SQL based dataset,FDQuery排序可以了
把SortLocal=true,也不能排序,报错 TSQLDatasetFeaturesEh can not sort data in dataset "FDMemTable1" in local mode
TFDMemTable不能排序,ClientDatSet替换为TFDMemTable的进程又得延缓.
比较和跟踪源码,Delphi里TFDMemTable排序正常。c++builder新建一个工程添加内存表和数据也排序正常。

最终解决了,原来是旧的ehlib控件卸载不干净,原来的工程里还有路径和ehlib.lib文件的链接,清除后排序全部OK!

2019.4.1 一个界面A 排序报错TFDMemTable is not SQL based dataset,弹出窗口排序正确,为什么呢,</pre>
<div class="hide-preCode-box"><span class="hide-preCode-bt"><img alt="" class="look-more-preCode contentImg-no-view lazyload" title="" data-src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png"></span></div>
<pre><code class="hljs language-undefined">FDQuery.Fields.DataSet</code> ?这也是数据集?
Data.DB.TFields.DataSet
Identifies the dataset to which a TFields object belongs.</pre>
<pre name="code">&nbsp;A DataTable or a DataView must be supplied. Hint: if that is TFDMemTable, use CreateDataSet or CloneCursor to open dataset

TFDDataSet 基类

fdquery,dbgrideh控件的ftsum字段求和影响

C++Builder 返回数据集
_di_IFDDataSetReference

<strong>16)已有数据的FDMemTable添加列,动态添加列
原有数据集,现有数据集,现有字段,原有字段,添加新增选择列</strong>
&nbsp; FDMemTable2.FieldDefs := FDMemTable1.FieldDefs;
&nbsp; FDMemTable2.FieldDefs.Add('Test', ftString, 20 { , False } ); // default parameter
&nbsp; FDMemTable2.FieldDefs.Find('Test').Index := 0;
&nbsp; FDMemTable2.CreateDataSet; // or just Open that sets Active to true;
&nbsp; FDMemTable2.CopyDataSet(FDMemTable1);

17)缓存更新
FDMemTable1-&gt;ChangeCount
执行了ApplyUpdates或CommitUpdates后ChangeCount变为0
FDMemTable1-&gt;ApplyUpdates(0);

<strong>C++builder Berlin//Berlin 排序无效</strong> 2017.3.12
delphi正常

升序
self.FDMemTable1.IndexFieldNames := 'ID:A';

降序
self.FDMemTable1.IndexFieldNames := 'ID:D';

FDMemTable1-&gt;IndexFieldNames = "ID:D";


FDMemTable1-&gt;CloneCursor(m-&gt;dsModule, true, true);</pre>
<pre>CloneCurso的数据集均无法用IndexFieldNames排序。用CreateDataSet创建的数据集排序正常!

Data赋值、CopyDataSet后的数据集均排序可以正常。建议不用CloneCursor。


<strong>18.修改只读字段</strong>
query1.UpdateOptions.AssignedValues =
&nbsp;&nbsp;&nbsp; FDStoredProc1-&gt;UpdateOptions-&gt;CheckReadOnly = false;

</pre>
<pre name="code"><strong>TSQLTimeStampField</strong>
ClientDataSet1: Type mismatch for field 'ffdatetimie', expecting: DateTime actual: TimeStamp
TDateTimeField
TDateTime 替换为
TSQLTimeStampField

<strong>FMTBcd</strong>
ds1: Type mismatch for field 'UNITPRICE', expecting: Float actual: FMTBcd.
TFloatField *ds1UNITPRICE;
TBCDField
替换为
TFMTBCDField

numeric(18,0)&nbsp;&nbsp; TFMTBCDField
decimal(18,4)&nbsp; TBCDField
ff3 decimal(18,3) TFMTBCDField
可能fdquery认为4位小数就设计器添加到字段列表是TBCDField,非4位小数就是TFMTBCDField,包括0 1 2 3 位小数。</pre>
<pre><strong>Caching_Updates_</strong></pre>
<pre>http://docwiki.embarcadero.com/RADStudio/Rio/en/Caching_Updates_(FireDAC)</pre>
<pre name="code">FDQuery1.CachedUpdates := True;
iSavePoint := FDQuery1.SavePoint;
try
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
except
FDQuery.SavePoint := iSavePoint;
end;


</pre>
<pre name="code">FDQuery1.CachedUpdates := True;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDConnection1.StartTransaction;
iErrors := FDQuery1.ApplyUpdates;
if iErrors = 0 then begin
FDQuery1.CommitUpdates;
FDConnection1.Commit;
end
else
FDConnection1.Rollback;


</pre>
<pre name="code">var
oErr: EFDException;
...
if FDQuery1.ApplyUpdates &gt; 0 then begin
FDQuery1.FilterChanges := ;
try
    FDQuery1.First;
    while not FDQuery1.Eof do begin
      oErr := FDQuery1.RowError;
      if oErr &lt;&gt; nil then begin
      // process exception object
      ...
      end;
      FDQuery1.Next;
    end;
finally
    FDQuery1.FilterChanges := ;
end;
end;
<strong>19)AppendData</strong>
2个完全一样的数据集合并 AppendData
ADOQuery1-&gt;AppendData(ADOQuery2-&gt;Data );
不用循环遍历了,一行命令搞定</pre>
</div><br><br>
来源:https://www.cnblogs.com/xionda/p/16163112.html
頁: [1]
查看完整版本: delphi 新版内存表 FDMemTable