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++)
 {
  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
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 );
不用循環遍歷了,一行命令搞定


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM