delphi 新版内存表 FDMemTable
c++builder XE
官方demo最全60多个
http://community.embarcadero.com/blogs?view=entry&id=8761
FireDAC.Comp.Client
用好FDMemTable代替之前的ClientDataSet,以前ClientDataSet内存表转换太繁琐了步骤。
TClientDataSet *cds = new TClientDataSet(this);
DataSetProvider1->DataSet = dm->ADOQueryPub;
cds->ProviderName = "DataSetProvider1";
cds->Open();
c++智能指针
#include <memory> //For STL auto_ptr class
std::auto_ptr<TFDMemTable> table (new TFDMemTable(NULL));
一句就可以了
FDMemTable1->CopyDataSet(dm->ADOQueryPub, TFDCopyDataSetOptions() << coStructure << coRestart << coAppend);
多用FDMemTable,不再用ClientDataSet\DataSetProvider1做转换了
FDMemTable2->Data = FDMemTable1->Data;
FDMemTable2->CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() << coStructure << coRestart << coAppend);
建立缓存表
FDMemTable1.Close(); FDMemTable1.FieldDefs.Clear(); FDMemTable1.FieldDefs.Add('ID', ftInteger, 0, True); FDMemTable1.FieldDefs.Add('Name', ftString, 20, false); FDMemTable1.CreateDataSet(); FDMemTable1.AppendRecord([101, 'aaa']); FDMemTable1.AppendRecord([102, 'bbb']); FDMemTable1.AppendRecord([103, 'ccc']);
0)FDMemTable1.SourceView遍历各行数据,取任意行数据无需Next移动指针了。TFDDatSView
for (int i = 0; i < FDMemTable1->SourceView->Rows->Count; i++)
{undefined
Caption = FDMemTable1->SourceView->Rows->ItemsI[i]->GetData(1);
}
FDMemTable1->SourceView->Rows->ItemsI[i]->GetData("fieldName");//取指定行指定字段名的值
}
9行7列的值。
FDMemTable1.Data.DataView.Rows.ItemsI[9].ValueI[7];
FDMemTable1.Table.Rows[i].ValueI[oCol.Index]
Caption = FDMemTable1->SourceView->Rows->Count;//过滤后1条
Caption = FDMemTable1->Table->Rows->Count;//过滤无效,全部记录3条
iMax := 0; for i := 0 to FDQuery1.SourceView.Rows.Count - 1 do if FDQuery1.SourceView.Rows[i].GetData('id', @iVal) and (iVal > iMax) then iMax := iVal
数据集拷贝,复制数据集,合并数据集
FDMemTable1->Filter = "id=102";
FDMemTable1->Filtered = true;
FDMemTable1只有1条记录
1)Data
FDMemTable2->Data = FDMemTable1->Data;
FDQuery->Open("select * from tt");
FDMemTable2->Data = FDQuery->Data;
FDMemTable2是全部记录,有3条记录。
FDMemTable1->Delete();后的记录不在Data里。
2)CopyDataSet
带结构拷贝
FDMemTable2->CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() << coStructure << coRestart << coAppend);
FDMemTable2->CommitUpdates();
缓存更新用到changeCount,所以copy完后加上CommitUpdates
不带结构,仅拷贝数据,字段个数可以不一致,字段数以目标数据集FDMemTable2为标准。
FDMemTable2->CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() << coRestart << coAppend);
//第二个参数默认是coRestart << coAppend,所以下面就更简单了。
FDMemTable2->CopyDataSet(FDMemTable1);
FDMemTable2只有1条记录
3)CopyRecord\CopyField
copy the current record field values .Only One Record
FDMemTable2->CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() << coStructure);
FDMemTable2->Edit();
FDMemTable2->CopyRecord(FDMemTable1);
4)CloneCursor
All Record, ignore filter
CloneCursor,数据共享,一个修改,另一个也修改了,但是FDMemTable1->Close之后FDMemTable2还正常显示。
FDMemTable2->CloneCursor( FDMemTable1);
2016.3.4 test 不能排序,FDMemTable2->IndexFieldNames = "ID";不起作用,所以尽量不建议用这个方式。
5)AtrachTable
All Record,ignore filter,TFDDatSTable
FDMemTable2->AttachTable(FDMemTable1->Table, NULL);
//or
//FDMemTable2->AttachTable(FDMemTable1->Table,FDMemTable1->View);
FDMemTable2->Open();
6)FilteredData
FDQuery1.Filter := 'upper(name) like ''D%'''; FDQuery1.Filtered := True; // copy to FDMemTable1 all FDQuery1 visible (where name starts from D) records FDMemTable1.Data := FDQuery1.FilteredData; RecordCount是过滤后的记录数。过滤前有100行,过滤后有5行,那么RecordCount就是5 FDQuery1->Data是100行,FilteredData是5行的数据 7)XMLData All Record ignore filter Memo1->Text = FDMemTable1->XMLData; FDMemTable2->XMLData = Memo1->Text; FDMemTable1->ChangeCount, 通过Data赋值,默认全部记录都是修改过的,也就是ChangeCount=RecordCount,有100条记录,获取ChangeCount属性就是100.这样合适还是不合适呢? FDMemTable1->Data = FDQuery->Data; FDMemTable1->CancelUpdates();或者FDMemTable1->CommitUpdates(); 加上CancelUpdates这句话,ChangeCount就正常了!!反应真实的修改记录数。 Append的记录需要把属性CachedUpdates设为true,ChangeCount就正确了。 8)Delta IFDDataSetReference类型 FDMemTable2->Delta= FDMemTable1->Delta; ADMemTable1.FilterChanges := [rtModified, rtInserted, rtDeleted]; ADMemTable1.Data := ADQuery1.Delta; 9)查看删除过的记录UpdateStatus FDMemTable想要找到并显示删除的记录 FDMemTable1->Delete(); FDMemTable2->FilterChanges << Firedac::Comp::Dataset::rtDeleted; FDMemTable1->Data = FDMemTable1->Data; while (!FDMemTable1.eof) { if( table->UpdateStatus() == usDeleted) ... } 默认是不显示删除过的记录的,FilterChanges不包括rtDeleted属性。 10)分页及加载全部页 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
11)增强的Locate功能LocateEx、LookupEx函数
lxoCheckOnly If included, then LocateEx does not:
Change the current position. Fire BeforeScroll / AfterScroll events. Finish editing mode 不改变位置和编辑状态的搜索,强大! 12)刷新数据集 query1.Refresh(); 13)只读字段 select '' as temp,flag=0,sql返回的虚拟字段,以前clientDataSet可以修改,FDMemTable里不能改了。 ClientDataSet1->FieldByName("flag")->AsString="1"; 但是FDMemTable不能改了。怎么办?以前的这种虚拟字段的方式挺好用啊。 解决办法:设置属性TFDMemTable.UpdateOptions.CheckReadonly=true 14)主从表关系
第一步: fdqueryDetail.MasterSource := DataSource1; 第二步: fdqueryDetail.MasterFields := 'OrderNo'; { 多个字段时用分号隔开 } 或者 fdqueryDetail.sql.text='select * from OrderDetail where OrderMasterKey=:OrderMasterKey'; 两个FDMemTable做主从怎么不起作用呢? 15)过滤数据FilterChanges 只显示修改后的数据 ClientDataSet1->FilterChanges = TFDUpdateRecordTypes() << 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,弹出窗口排序正确,为什么呢,
FDQuery.Fields.DataSet
?这也是数据集?
Data.DB.TFields.DataSet
Identifies the dataset to which a TFields object belongs.
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 16)已有数据的FDMemTable添加列,动态添加列 原有数据集,现有数据集,现有字段,原有字段,添加新增选择列 FDMemTable2.FieldDefs := FDMemTable1.FieldDefs; FDMemTable2.FieldDefs.Add('Test', ftString, 20 { , False } ); // default parameter FDMemTable2.FieldDefs.Find('Test').Index := 0; FDMemTable2.CreateDataSet; // or just Open that sets Active to true; FDMemTable2.CopyDataSet(FDMemTable1); 17)缓存更新 FDMemTable1->ChangeCount 执行了ApplyUpdates或CommitUpdates后ChangeCount变为0 FDMemTable1->ApplyUpdates(0); C++builder Berlin //Berlin 排序无效 2017.3.12 delphi正常 升序 self.FDMemTable1.IndexFieldNames := 'ID:A'; 降序 self.FDMemTable1.IndexFieldNames := 'ID:D'; FDMemTable1->IndexFieldNames = "ID:D"; FDMemTable1->CloneCursor(m->dsModule, true, true);
CloneCurso的数据集均无法用IndexFieldNames排序。用CreateDataSet创建的数据集排序正常! Data赋值、CopyDataSet后的数据集均排序可以正常。建议不用CloneCursor。 18.修改只读字段 query1.UpdateOptions.AssignedValues = [uvCheckReadOnly] FDStoredProc1->UpdateOptions->CheckReadOnly = false;
TSQLTimeStampField ClientDataSet1: Type mismatch for field 'ffdatetimie', expecting: DateTime actual: TimeStamp TDateTimeField TDateTime 替换为 TSQLTimeStampField FMTBcd ds1: Type mismatch for field 'UNITPRICE', expecting: Float actual: FMTBcd. TFloatField *ds1UNITPRICE; TBCDField 替换为 TFMTBCDField [Amount] numeric(18,0) TFMTBCDField [PhPrice] decimal(18,4) TBCDField ff3 decimal(18,3) TFMTBCDField 可能fdquery认为4位小数就设计器添加到字段列表是TBCDField,非4位小数就是TFMTBCDField,包括0 1 2 3 位小数。
Caching_Updates_
http://docwiki.embarcadero.com/RADStudio/Rio/en/Caching_Updates_(FireDAC)
FDQuery1.CachedUpdates := True; iSavePoint := FDQuery1.SavePoint; try FDQuery1.Append; ... FDQuery1.Post; FDQuery1.Append; ... FDQuery1.Post; FDQuery1.Append; ... FDQuery1.Post; except FDQuery.SavePoint := iSavePoint; end;
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;
var oErr: EFDException; ... if FDQuery1.ApplyUpdates > 0 then begin FDQuery1.FilterChanges := [rtModified, rtInserted, rtDeleted, rtHasErrors]; try FDQuery1.First; while not FDQuery1.Eof do begin oErr := FDQuery1.RowError; if oErr <> nil then begin // process exception object ... end; FDQuery1.Next; end; finally FDQuery1.FilterChanges := [rtUnmodified, rtModified, rtInserted]; end; end; 19)AppendData 2个完全一样的数据集合并 AppendData ADOQuery1->AppendData(ADOQuery2->Data ); 不用循环遍历了,一行命令搞定