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));
for (table->First(); !table->Eof; table->Next())
{
table->FieldByName("aa")->AsString;
}
一句就可以了
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
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
不改變位置和編輯狀態的搜尋,強大!
if (ds1->LocateEx("DM", "001", TFDDataSetLocateOptions() << lxoCheckOnly))
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 位小數。
19.建立索引
FDQueryRelation.AddIndex('index1','ITEMTYPE;ITEMNOHIS','', []);
FDQueryRelation.IndexName := 'index1';
經過試驗證明,filter沒有使用索引,支援like表示式
locate和findkey使用了索引,精確定位,要求檢索速度快,檢驗使用
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 );
不用迴圈遍歷了,一行命令搞定
void __fastcall Tfrm::ds1UpdateError(TDataSet *ASender, EFDException *AException,
TFDDatSRow *ARow, TFDUpdateRequest ARequest, TFDErrorAction &AAction)
{
throw new Exception( AException->Message );
}
20.fdmemtable批次編輯效能最佳化
http://docwiki.embarcadero.com/RADStudio/Rio/en/TFDMemTable_Questions
例如 Set the following properties LogChanges, FetchOptions, ResourceOptions, and UpdateOptions.
FDMemTable1.LogChanges := False;
FDMemTable1.FetchOptions.RecsMax := 300000; //Sample value
FDMemTable1.ResourceOptions.SilentMode := True;
FDMemTable1.UpdateOptions.LockMode := lmNone;
FDMemTable1.UpdateOptions.LockPoint := lpDeferred;
FDMemTable1.UpdateOptions.FetchGeneratorsPoint := gpImmediate;
Then surround massive edition operations into BeginBatch / EndBatch method calls:
FDMemTable1.BeginBatch;
try
for i := 1 to 1000 do begin
FDMemTable1.Append;
// ...
FDMemTable1.Post;
end;
finally
FDMemTable1.EndBatch;
end;
c#
DataTable dataFee;
DataRow[] drRerr = dataFee.Select("目錄類別=''");
複製表有兩種方法
DataTable.Clone() 只克隆表結構
DataTable.Copy() 克隆表結構及資料
DataTable dt2 = dt.Clone();
var rows = dataFee.Select("col3>=30", "col3 desc");
if (rows != null && rows.Length > 0)
{
foreach (DataRow row in rows)
{
dt2.ImportRow(row);
}
}
FDConnection1一句話執行SQL
FDConnection1.ExecSQL('truncate table tab1'); FDConnection1.ExecSQL('drop table tab2', True); FDConnection1.ExecSQL('delete from mytab where id > :p1', [1000]); FDConnection1.ExecSQL('update mytab where id = :p1 set blobfld = :blb', [1000, StringOfChar('x', 100000)], [ftInteger, ftBLOB]);
多表查詢更新
FDQuery1->UpdateOptions->UpdateTableName="T_USER_B";//聯合查詢 更新指定的表
FDQuery1->FieldByName("NAME")->ProviderFlags.Clear();//不更新該欄位
克隆
FClonedDataSet := Table.FDataSet.GetClonedDataSet(True);
if FClonedDataSet = nil then begin
FClonedDataSet := TFDMemTable.Create(nil);
TFDMemTable(FClonedDataSet).CopyDataSet(Table.FDataSet, [coStructure, coCalcFields,
coRestart, coAppend, coIndexesCopy, coConstraintsCopy, coAggregatesCopy]);