Bảng nhớ trong FDMemTable trong Delphi mới

C++Builder XE

Demo chính thức đầy đủ hơn 60 mẫu

http://community.embarcadero.com/blogs?view=entry&id=8761

FireDAC.Comp.Client

Sử dụng FDMemTable tốt hơn thay vì ClientDataSet trước đây, việc chuyển đổi bảng nhớ từ ClientDataSet quá phức tạp.

TClientDataSet *cds = new TClientDataSet(this); DataSetProvider1->DataSet = dm->ADOQueryPub; cds->ProviderName = "DataSetProvider1"; cds->Open();

Sử dụng smart pointer trong C++

#include //For STL auto_ptr class

std::auto_ptr table (new TFDMemTable(NULL));

Chỉ cần một dòng lệnh

FDMemTable1->CopyDataSet(dm->ADOQueryPub, TFDCopyDataSetOptions() CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() Count; i++) {undefined Caption = FDMemTable1->SourceView->Rows->ItemsI[i]->GetData(1); }

FDMemTable1->SourceView->Rows->ItemsI[i]->GetData("fieldName");//Lấy giá trị của trường cụ thể tại hàng chỉ định }

Giá trị của ô tại hàng 9 cột 7.

FDMemTable1.Data.DataView.Rows.ItemsI[9].ValueI[7];

FDMemTable1.Table.Rows[i].ValueI[oCol.Index]

Caption = FDMemTable1->SourceView->Rows->Count;//Sau khi lọc chỉ còn 1 bản ghi Caption = FDMemTable1->Table->Rows->Count;//Không lọc được, hiển thị tất cả 3 bản ghi

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

Sao chép tập dữ liệu, sao chép dữ liệu, hợp nhất tập dữ liệu

FDMemTable1->Filter = "id=102"; FDMemTable1->Filtered = true;

Chỉ có 1 bản ghi sau khi lọc

1) Data

FDMemTable2->Data = FDMemTable1->Data;

FDQuery->Open("select * from tt");

FDMemTable2->Data = FDQuery->Data;

FDMemTable2 chứa toàn bộ bản ghi, có 3 bản ghi.

Bản ghi bị xóa sẽ không còn trong Data sau khi gọi Delete()

2) CopyDataSet

Sao chép cấu trúc

FDMemTable2->CopyDataSet(FDMemTable1, TFDCopyDataSetOptions() CloneCursor( FDMemTable1);

2016.3.4 kiểm tra, không thể sắp xếp, FDMemTable2->IndexFieldNames = "ID"; không hoạt động, nên tránh sử dụng cách này.

5) AttachTable

Tất cả bản ghi, bỏ qua bộ lọc, TFDDatSTable

FDMemTable2->AttachTable(FDMemTable1->Table, NULL);

//hoặc

//FDMemTable2->AttachTable(FDMemTable1->Table,FDMemTable1->View); FDMemTable2->Open();

6) FilteredData

FDQuery1.Filter := 'upper(name) like ''D%''';
FDQuery1.Filtered := True;
<em>// sao chép tất cả bản ghi từ FDQuery1 có tên bắt đầu bằng D vào FDMemTable1</em>
FDMemTable1.Data := FDQuery1.FilteredData;

RecordCount là số bản ghi sau khi lọc. Trước khi lọc có 100 hàng, sau lọc chỉ còn 5 hàng, vậy RecordCount là 5
FDQuery1->Data có 100 hàng, FilteredData có 5 hàng dữ liệu
<strong>7) XMLData
</strong>Tất cả bản ghi, bỏ qua bộ lọc
 Memo1->Text = FDMemTable1->XMLData;
 FDMemTable2->XMLData = Memo1->Text;

FDMemTable1->ChangeCount,
Khi gán dữ liệu qua Data, mặc định tất cả bản ghi đều được đánh dấu đã sửa đổi, tức là ChangeCount=RecordCount, có 100 bản ghi, ChangeCount sẽ là 100. Điều này đúng hay sai?
FDMemTable1->Data = FDQuery->Data;
FDMemTable1->CancelUpdates(); hoặc FDMemTable1->CommitUpdates();
Thêm dòng CancelUpdates, ChangeCount sẽ trở lại đúng! Phản ánh chính xác số bản ghi đã sửa.
Bản ghi thêm mới cần thiết lập thuộc tính CachedUpdates thành true, ChangeCount sẽ chính xác.
<strong>8) Delta
Loại IFDDataSetReference</strong>
FDMemTable2->Delta= FDMemTable1->Delta;

ADMemTable1.FilterChanges := [rtModified, rtInserted, rtDeleted]; 
ADMemTable1.Data := ADQuery1.Delta;

<strong>9) Kiểm tra bản ghi bị xóa UpdateStatus</strong>

<strong>Muốn tìm và hiển thị bản ghi bị xóa trong FDMemTable</strong>
   FDMemTable1->Delete();
   FDMemTable2->FilterChanges << Firedac::Comp::Dataset::rtDeleted;
   FDMemTable1->Data = FDMemTable1->Data; 
while (!FDMemTable1.eof)
{
if( table->UpdateStatus() == usDeleted)
...
}
Mặc định không hiển thị bản ghi bị xóa, FilterChanges không bao gồm rtDeleted.
<strong>10) Phân trang và tải toàn bộ trang</strong>
Mode mặc định FetchOptions là fmOnDemand cho phân trang, mỗi trang 50 bản ghi, thay đổi thành fmAll để tải toàn bộ.
Phân trang TFDFetchOptions.RowsetSize
FetchNext
FetchAll
FetchOptions.RecordCountMode property

FDQuery1.Open;
FDQuery1.FetchAll;//Phải thêm dòng này, nếu không dữ liệu sẽ không đầy đủ.
FDMemTable1.Data := FDQuery1.Data;
Sử dụng grideh, tại sao phân trang không hoạt động? Tất cả bản ghi đều hiển thị? Vì trường ftsum gây ra vấn đề, bỏ trường này thì mỗi lần chỉ 50 bản ghi.

LocateEx
  1. Tính năng Locate nâng cao LocateEx, LookupEx
lxoCheckOnly  Nếu có mặt, LocateEx không:
Thay đổi vị trí hiện tại. Gây ra sự kiện BeforeScroll / AfterScroll. Kết thúc chế độ chỉnh sửa
Tìm kiếm không làm thay đổi vị trí và trạng thái chỉnh sửa, rất mạnh!
<strong>12) Làm mới tập dữ liệu</strong>
query1.Refresh();

<strong>13) Trường chỉ đọc</strong>
select  '' as temp,flag=0, trường ảo trả về từ SQL, trước đây ClientDataSet có thể chỉnh sửa, nhưng FDMemTable không cho phép chỉnh sửa.
ClientDataSet1->FieldByName("flag")->AsString="1";
Nhưng FDMemTable không cho phép chỉnh sửa. Làm sao bây giờ? Cách dùng trường ảo trước đây rất tiện lợi.
Giải pháp: Thiết lập thuộc tính TFDMemTable.UpdateOptions.CheckReadonly=true

<strong>14) Quan hệ giữa bảng chính và phụ</strong>
Bước 1:
fdqueryDetail.MasterSource := DataSource1;
Bước 2:
 fdqueryDetail.MasterFields := 'OrderNo'; { nhiều trường dùng dấu chấm phẩy để phân tách }
hoặc
fdqueryDetail.sql.text='select * from OrderDetail where OrderMasterKey=:OrderMasterKey';

Hai FDMemTable làm bảng chính phụ không hoạt động?

<strong>15) Lọc dữ liệu FilterChanges</strong>
Chỉ hiển thị dữ liệu đã sửa đổi
ClientDataSet1->FilterChanges = TFDUpdateRecordTypes() << Firedac::Comp::Dataset::rtModified;

ClientDatSet dùng với Grideh có thể sắp xếp, thêm file EhLibCDS.pas.
TFDMemTable thêm EhLibFireDAC.pas không thể sắp xếp, báo lỗi TFDMemTable is not SQL based dataset, FDQuery sắp xếp được.
Đặt SortLocal=true, cũng không thể sắp xếp, báo lỗi TSQLDatasetFeaturesEh không thể sắp xếp dữ liệu trong tập dữ liệu "FDMemTable1" ở chế độ cục bộ
TFDMemTable không thể sắp xếp, quá trình thay thế ClientDataSet bằng TFDMemTable phải trì hoãn.
So sánh và theo dõi mã nguồn, trong Delphi TFDMemTable sắp xếp bình thường. Trong C++Builder tạo mới project với bảng nhớ và dữ liệu cũng sắp xếp bình thường.

Cuối cùng giải quyết được, nguyên nhân là do component ehlib cũ chưa gỡ hoàn toàn, vẫn còn đường dẫn và liên kết đến ehlib.lib trong project, sau khi loại bỏ thì sắp xếp hoàn toàn OK!

2019.4.1 Giao diện A sắp xếp bị lỗi TFDMemTable is not SQL based dataset, cửa sổ bật lên sắp xếp đúng, tại sao vậy?

FDQuery.Fields.DataSet

Data.DB.TFields.DataSet
Xác định tập dữ liệu mà đối tượng TFields thuộc về.
 Một DataTable hoặc DataView phải được cung cấp. Gợi ý: nếu đó là TFDMemTable, hãy dùng CreateDataSet hoặc CloneCursor để mở tập dữ liệu

TFDDataSet lớp cơ sở

fdquery, trường ftsum của dbgrideh ảnh hưởng

Trả về tập dữ liệu trong C++Builder
_di_IFDDataSetReference

<strong>16) Thêm cột vào FDMemTable có sẵn dữ liệu, thêm cột động</strong>
Tập dữ liệu hiện tại, tập dữ liệu mới, trường hiện tại, trường cũ, thêm cột chọn mới
  FDMemTable2.FieldDefs := FDMemTable1.FieldDefs;
  FDMemTable2.FieldDefs.Add('Test', ftString, 20 { , False } ); // tham số mặc định
  FDMemTable2.FieldDefs.Find('Test').Index := 0;
  FDMemTable2.CreateDataSet; // hoặc chỉ cần Open để Active = true;
  FDMemTable2.CopyDataSet(FDMemTable1);

17) Cập nhật cache
FDMemTable1->ChangeCount 
Sau khi ApplyUpdates hoặc CommitUpdates, ChangeCount trở về 0
FDMemTable1->ApplyUpdates(0);

<strong>C++builder Berlin  //Sắp xếp không hoạt động trong Berlin</strong> 2017.3.12
Delphi hoạt động bình thường

Tăng dần
self.FDMemTable1.IndexFieldNames := 'ID:A';

Giảm dần
self.FDMemTable1.IndexFieldNames := 'ID:D';

FDMemTable1->IndexFieldNames = "ID:D";


FDMemTable1->CloneCursor(m->dsModule, true, true);
Dữ liệu tập dữ liệu CloneCursor không thể sắp xếp bằng IndexFieldNames. Tập dữ liệu tạo bởi CreateDataSet sắp xếp bình thường!

Dữ liệu sau khi gán Data, CopyDataSet đều sắp xếp được bình thường. Nên tránh dùng CloneCursor.


<strong>18. Chỉnh sửa trường chỉ đọc</strong>
query1.UpdateOptions.AssignedValues = [uvCheckReadOnly]
    FDStoredProc1->UpdateOptions->CheckReadOnly = false;

<strong>Trường TSQLTimeStampField</strong>
ClientDataSet1: Không phù hợp kiểu dữ liệu cho trường 'ffdatetimie', mong đợi: DateTime thực tế: TimeStamp
TDateTimeField
TDateTime thay thế bằng
TSQLTimeStampField

<strong>FMTBcd</strong>
ds1: Không phù hợp kiểu dữ liệu cho trường 'UNITPRICE', mong đợi: Float thực tế: FMTBcd.
TFloatField *ds1UNITPRICE;
TBCDField
Thay thế bằng
TFMTBCDField

[Amount] numeric(18,0)   TFMTBCDField
[PhPrice] decimal(18,4)  TBCDField
ff3 decimal(18,3) TFMTBCDField
Có thể FDQuery cho rằng 4 chữ số thập phân thì thiết kế thêm vào danh sách trường là TBCDField, nếu khác 4 chữ số thì là TFMTBCDField, bao gồm 0, 1, 2, 3 chữ số thập phân.
<strong>Caching_Updates_</strong>
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
        // xử lý đối tượng ngoại lệ
        ...
      end;
      FDQuery1.Next;
    end;
  finally
    FDQuery1.FilterChanges := [rtUnmodified, rtModified, rtInserted];
  end;
end;
<strong>19) AppendData</strong>
Hợp nhất 2 tập dữ liệu giống hệt nhau bằng AppendData
ADOQuery1->AppendData(ADOQuery2->Data );
Không cần vòng lặp, chỉ cần một lệnh đơn giản

Thẻ: Delphi FDMemTable FireDAC C++Builder Dataset

Đăng vào ngày 26 tháng 6 lúc 23:22