使用FDBatchMove将CSV文件导入FDTableTask

时间:2016-10-11 22:05:10

标签: csv delphi import interbase delphi-10.1-berlin

我正在开始我的第一个需要嵌入式数据库的应用程序,能够将CSV导入表格并将结果显示到网格中。我使用Live Binding Wizard将我的网格链接到BindSourceDB。以下是我使用的基本组件:

BindingsList1: TBindingsList;
LinkFillControlToField1: TLinkFillControlToField;
BindSourceDB1: TBindSourceDB;
FireTaskList: TFDConnection;
FDTableTask: TFDTable;
FDQuery: TFDQuery;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
FDPhysIBDriverLink1: TFDPhysIBDriverLink;
FDTableTaskDATE: TDateField;
FDTableTaskDESCRIPTION: TStringField;
FDTableTaskORIGDESC: TStringField;
FDTableTaskAMOUNT: TIntegerField;
FDTableTaskTYPE: TStringField;
FDTableTaskCATEGORY: TStringField;
FDTableTaskACCTNAME: TStringField;
FDTableTaskLABELS: TStringField;
FDTableTaskNOTES: TMemoField;
FDBatchMove1: TFDBatchMove;
FDBatchMoveTextReader1: TFDBatchMoveTextReader;
FDBatchMoveDataSetWriter1: TFDBatchMoveDataSetWriter;
OpenDialog1: TOpenDialog;
Grid1: TGrid;
LinkGridToDataSourceBindSourceDB1: TLinkGridToDataSource;

第一个问题,导入文件总共7列,总共5500行或记录的文件是一个非常缓慢的过程。我为我的FDBatchMoveTextReader设置了添加文件字段的CSV文件。我设置我的FDBatchMoveDataSetWriter来写入数据集FDTableTask并将表格的字段分配给它。

这是我的基本代码:

if OpenDialog1.Execute then
begin
  ShowMessage('Start read'); // more then 5 secods before this displays (sometimes)
  FDBatchMoveTextReader1.FileName := OpenDialog1.FileName;
  ShowMessage('Start Move'); // Dispalys instantly
  FDBatchMove1.Execute;
  Showmessage('done'); //About 25 seconds before this displays
end;

它有效,但需要很长时间。在Delphi 5中使用DBISAM和CSV Import组件执行此操作,整个过程就像5秒钟。我只有FDBatchMove组件的默认设置。这不仅需要很长时间,而且我通过将FDBatchMove1.Options设置为[poClearDest,poIdentityInsert]来替换FDTableTask表中的数据。

过程很慢,网格永远不会重新填充新的文件数据,直到我关闭并重新打开应用程序。如何在流程完成后更快地完成此过程并在网格中显示新数据?

1 个答案:

答案 0 :(得分:1)

更新鉴于您的评论,我已经第三次更新了这个,以展示一个尽可能接近我的代码并且似乎没有受到影响的示例你说你遇到的问题。我只能建议你自己尝试,然后尝试确定你自己的原因 项目的行为方式不同。我不打算再花钱了 时间在此。

使用Live Bindings 方式比使用传统的db-aware组件慢。

那就是说,我恐怕无法重现你的问题。我设置了一个多设备FMX 项目如下面的代码和DFM提取。为了做到这一点 尽可能自包含,我已将所有组件和代码放在一个单独的组件中 表单单元,代码生成要导入的CSV文件。

正如您将看到编译和运行项目一样,应用程序以 StringGrid包含3行,并单击ImportCSV按钮生成和 进口额外9997行。这花了不到几秒钟就可以了 笔记本电脑。

请注意,ImportCSV的速度没有任何明显变化 过程,如果我注释掉对DisableControls和EnableControls的调用。这个 我略微感到惊讶,但也许TFDBatchMove在内部做了这个或类似的事情。

此示例应用程序显示了LiveBindings的怪癖(至少在西雅图)。没有 在FDMemTable1.FirstFormCreate,StringGrid中调用ImportCSV 仅在FormCreate后显示第3行,在ImportCSV后显示第1,2和10000行。

代码:

type
  TForm1 = class(TForm)
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    StringGrid1: TStringGrid;
    BindSourceDB1: TBindSourceDB;
    BindingsList1: TBindingsList;
    FDMemTable1: TFDMemTable;
    FDMemTable1ID: TIntegerField;
    FDMemTable1Name: TStringField;
    LinkGridToDataSource1: TLinkGridToDataSource;
    FDBatchMove1: TFDBatchMove;
    FDBatchMoveDataSetWriter1: TFDBatchMoveDataSetWriter;
    Button1: TButton;
    BindNavigator1: TBindNavigator;
    FDBatchMoveTextReader1: TFDBatchMoveTextReader;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure ImportCSV;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  ImportCSV;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FDMemTable1.IndexFieldNames := 'ID';
  FDMemTable1.CreateDataSet;
  FDMemTable1.InsertRecord([1, 'One']);
  FDMemTable1.InsertRecord([2, 'Two']);
  FDMemTable1.InsertRecord([3, 'Three']);
  FDMemTable1.First;
end;

procedure TForm1.ImportCSV;
var
  AFileName : String;
  TL : TStringList;
  i : Integer;
begin
  AFileName := 'c:\temp\book1.csv';

  try
    TL := TStringList.Create;
    for i := 4 to 10000 do
      TL.Add(IntToStr(i) + ',' + 'Row ' + IntToStr(i));

    TL.SaveToFile(AFileName);

    FDMemTable1.DisableControls;
    FDBatchMoveTextReader1.FileName := AFileName;
    FDBatchMove1.Execute;
    FDMemTable1.First;
  finally
    FDMemTable1.EnableControls;
    TL.Free;
  end;
end;

DFM

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 480
  ClientWidth = 429
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object StringGrid1: TStringGrid
    Position.X = 8.000000000000000000
    Position.Y = 8.000000000000000000
    Size.Width = 409.000000000000000000
    Size.Height = 201.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 3
    RowCount = 100
    RowHeight = 21.000000000000000000
    Viewport.Width = 389.000000000000000000
    Viewport.Height = 176.000000000000000000
  end
  object Button1: TButton
    Position.X = 160.000000000000000000
    Position.Y = 288.000000000000000000
    TabOrder = 10
    Text = 'Button1'
    OnClick = Button1Click
  end
  object BindNavigator1: TBindNavigator
    Position.X = 8.000000000000000000
    Position.Y = 216.000000000000000000
    Size.Width = 240.000000000000000000
    Size.Height = 25.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 19
    DataSource = BindSourceDB1
    xRadius = 4.000000000000000000
    yRadius = 4.000000000000000000
  end
  object FDGUIxWaitCursor1: TFDGUIxWaitCursor
    Provider = 'FMX'
    Left = 352
    Top = 48
  end
  object BindSourceDB1: TBindSourceDB
    DataSet = FDMemTable1
    ScopeMappings = <>
    Left = 160
    Top = 48
  end
  object BindingsList1: TBindingsList
    Methods = <>
    OutputConverters = <>
    Left = 272
    Top = 48
    object LinkGridToDataSource1: TLinkGridToDataSource
      Category = 'Quick Bindings'
      DataSource = BindSourceDB1
      GridControl = StringGrid1
      Columns = <>
    end
  end
  object FDMemTable1: TFDMemTable
    FetchOptions.AssignedValues = [evMode]
    FetchOptions.Mode = fmAll
    ResourceOptions.AssignedValues = [rvSilentMode]
    ResourceOptions.SilentMode = True
    UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates]
    UpdateOptions.CheckRequired = False
    UpdateOptions.AutoCommitUpdates = True
    Left = 72
    Top = 48
    object FDMemTable1ID: TIntegerField
      FieldName = 'ID'
    end
    object FDMemTable1Name: TStringField
      FieldName = 'Name'
    end
  end
  object FDBatchMove1: TFDBatchMove
    Reader = FDBatchMoveTextReader1
    Writer = FDBatchMoveDataSetWriter1
    Mappings = <>
    LogFileName = 'c:\temp\Data.log'
    Left = 72
    Top = 136
  end
  object FDBatchMoveDataSetWriter1: TFDBatchMoveDataSetWriter
    DataSet = FDMemTable1
    Left = 352
    Top = 136
  end
  object FDBatchMoveTextReader1: TFDBatchMoveTextReader
    DataDef.Fields = <>
    Left = 192
    Top = 136
  end
end