Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 对象Pascal:TClientDataset删除_Delphi_Tclientdataset - Fatal编程技术网

Delphi 对象Pascal:TClientDataset删除

Delphi 对象Pascal:TClientDataset删除,delphi,tclientdataset,Delphi,Tclientdataset,我正在使用TClientDataset创建内存中的数据集,以用作接收缓冲区。添加数据很好,但一旦我开始处理它,我希望能够从数据集中删除该行。调用delete works-sort of-行/索引仍然可以访问,但现在不包含有效信息 这使得事情变得有点困难,因为当我处理这个缓冲区时,实际上并不能保证条目会被删除。我不希望从第一个条目开始扫描缓冲区并跳过空项,那么有更好的方法从数据集中永久“删除”该项吗?我的想法是,它应该像实际的SQL表一样工作,删除一行不会留下空记录 实现这一点的最佳方法是什么,或

我正在使用TClientDataset创建内存中的数据集,以用作接收缓冲区。添加数据很好,但一旦我开始处理它,我希望能够从数据集中删除该行。调用delete works-sort of-行/索引仍然可以访问,但现在不包含有效信息

这使得事情变得有点困难,因为当我处理这个缓冲区时,实际上并不能保证条目会被删除。我不希望从第一个条目开始扫描缓冲区并跳过空项,那么有更好的方法从数据集中永久“删除”该项吗?我的想法是,它应该像实际的SQL表一样工作,删除一行不会留下空记录


实现这一点的最佳方法是什么,或者我使用的组件完全错误?

默认情况下,客户端数据集包含更改的“日志”,因为它们还可以将客户端更改发送到远程服务器,即使这些更改是在断开连接的会话中进行的(“公文包模型”)。通常,当您将更改应用到远程数据库时,此日志会被“清除”,而任何其他更改都会与您的“本地”副本合并。
如果您不需要LogChanges并希望直接进行更改,请将其设置为False。

关于代码的几点说明

  • 您正在使用一种不寻常的方式在数据集中循环(使用计数器,但仍然使用next)

  • 删除时,我首选的方向是从头到尾

  • 删除后不发布数据集

  • 我的建议是尝试以下方式:

    MyDataSet.RecNo:= 99
    while not MyDataSet.Bof do
    begin
      fD1 := MyDataset.FieldByName('Field1').AsInteger;
      fD2 := MyDataset.FieldByName('Field2').AsInteger;
      fD3 := MyDataset.FieldByName('Field3').AsInteger;
    
      if someCondition then
        MyDataset.Delete;
    
      MyDataSet.Post;
    
      MyDataset.Previous;
    end;
    

    你的代码有问题。我为这个案例准备了一个测试应用程序,因为几天后我将在多线程环境中面对TClientDataSet。我的测试用例应用程序没有出现这个问题(Delphi2010更新5)

    我将在几天后在我自己的博客上发布这段代码。。。现在我给你的是:

    DFM文件:

    object Form2: TForm2
      Left = 0
      Top = 0
      Caption = 'Form2'
      ClientHeight = 337
      ClientWidth = 635
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnClose = FormClose
      PixelsPerInch = 96
      TextHeight = 13
      object Memo1: TMemo
        Left = 8
        Top = 8
        Width = 257
        Height = 321
        Lines.Strings = (
          'Memo1')
        TabOrder = 0
      end
      object Button1: TButton
        Left = 271
        Top = 8
        Width = 170
        Height = 25
        Caption = 'Start'
        TabOrder = 1
        OnClick = Button1Click
      end
      object cdsTest: TClientDataSet
        Aggregates = <>
        Params = <>
        Left = 584
        Top = 32
        object cdsTestNumber: TIntegerField
          FieldName = 'Number'
        end
      end
      object tToMemo: TTimer
        Enabled = False
        Interval = 500
        OnTimer = tToMemoTimer
        Left = 376
        Top = 144
      end
    end
    
    对象格式2:TForm2
    左=0
    Top=0
    标题='Form2'
    ClientHeight=337
    ClientWidth=635
    颜色=clBtnFace
    Font.Charset=默认字符集
    Font.Color=clWindowText
    字体高度=-11
    Font.Name='Tahoma'
    Font.Style=[]
    OldCreateOrder=False
    OnClose=FormClose
    PixelsPerInch=96
    text高度=13
    对象备忘录1:TMemo
    左=8
    Top=8
    宽度=257
    高度=321
    行。字符串=(
    "备忘录1")
    TabOrder=0
    结束
    对象按钮1:t按钮
    左=271
    Top=8
    宽度=170
    高度=25
    标题=‘开始’
    TabOrder=1
    OnClick=按钮1单击
    结束
    对象cdsTest:TClientDataSet
    聚合=
    参数=
    左=584
    Top=32
    对象CDST编号:TIntegerField
    字段名='Number'
    结束
    结束
    对象:TTimer
    已启用=错误
    间隔=500
    OnTimer=计时器
    左=376
    顶部=144
    结束
    结束
    
    pas文件:

    unit Unit2;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, DBClient, SyncObjs, ExtCtrls;
    
    type
      TWriterThread = class(TThread)
      private
        FDataSet: TClientDataSet;
        //FWriteLock: TMultiReadExclusiveWriteSynchronizer;
        FLock: TCriticalSection;
      public
        constructor Create(ADataSet: TClientDataSet; ALock: TCriticalSection);
        procedure Execute; override;
      end;
    
      TDeleterThread = class(TThread)
      private
        FDataSet: TClientDataSet;
        //FWriteLock: TMultiReadExclusiveWriteSynchronizer;
        FLock: TCriticalSection;
      public
        constructor Create(ADataSet: TClientDataSet; ALock: TCriticalSection);
        procedure Execute; override;
      end;
    
      TForm2 = class(TForm)
        cdsTest: TClientDataSet;
        Memo1: TMemo;
        cdsTestNumber: TIntegerField;
        Button1: TButton;
        tToMemo: TTimer;
        procedure Button1Click(Sender: TObject);
        procedure tToMemoTimer(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        FLock: TCriticalSection;
        FWriterThread: TWriterThread;
        FDeleterThread: TDeleterThread;
        procedure cdsToMemo;
      public
        { Public declarations }
      end;
    
    var
      Form2: TForm2;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      Button1.Enabled := False;
      cdsTest.CreateDataSet;
      cdsTest.LogChanges := False;
      FLock := TCriticalSection.Create;
      tToMemo.Enabled := True;
      FWriterThread := TWriterThread.Create(cdsTest, FLock);
      FDeleterThread := TDeleterThread.Create(cdsTest, FLock);
    end;
    
    { TWriterThread }
    
    constructor TWriterThread.Create(ADataSet: TClientDataSet;
      ALock: TCriticalSection);
    begin
      inherited Create(False);
      FDataSet := ADataSet;
      FLock := ALock;
    end;
    
    procedure TWriterThread.Execute;
    var
      I: Integer;
    begin
      inherited;
      I := 0;
      while not Terminated do
      begin
        FLock.Enter;
        try
          Inc(I);
          FDataSet.AppendRecord([I]);
        finally
          FLock.Leave;
        end;
        Sleep(500);  //a new record aproximately each half second
      end;
    end;
    
    { TDeleterThread }
    
    constructor TDeleterThread.Create(ADataSet: TClientDataSet;
      ALock: TCriticalSection);
    begin
      inherited Create(False);
      FDataSet := ADataSet;
      FLock := ALock;
    end;
    
    procedure TDeleterThread.Execute;
    const
      MaxRecords = 100;
    var
      ProcessedRecords: Integer;
    begin
      inherited;
      while not Terminated do
      begin
        Sleep(3000);  //delete records aproximately every 3 seconds
        FLock.Enter;
        try
          FDataSet.First;
          ProcessedRecords := 0;
          while (not FDataSet.Eof) and (ProcessedRecords < MaxRecords) do
          begin
            Inc(ProcessedRecords);
            if Odd(FDataSet.Fields[0].AsInteger) then
              FDataSet.Delete
            else
              FDataSet.Next;
          end;
        finally
          FLock.Leave;
        end;
      end;
    end;
    
    procedure TForm2.cdsToMemo;
    begin
      FLock.Enter;
      try
        Memo1.Lines.BeginUpdate;
        try
          Memo1.Lines.Clear;
          cdsTest.First;
          while not cdsTest.Eof do
          begin
            Memo1.Lines.Add(cdsTestNumber.AsString);
            cdsTest.Next;
          end;
        finally
          Memo1.Lines.EndUpdate;
        end;
      finally
        FLock.Leave;
      end;
    end;
    
    procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      tToMemo.Enabled := False;
      if cdsTest.Active then
      begin
        FDeleterThread.Terminate;
        FDeleterThread.WaitFor;
        FWriterThread.Terminate;
        FWriterThread.WaitFor;
      end;
    end;
    
    procedure TForm2.tToMemoTimer(Sender: TObject);
    begin
      tToMemo.Enabled := False;
      cdsToMemo;
      tToMemo.Enabled := True;
    end;
    
    end.
    
    单元2;
    接口
    使用
    窗口、消息、系统工具、变体、类、图形、控件、窗体、,
    对话框、StdCtrls、DB、DBClient、SyncObjs、ExtCtrls;
    类型
    TWriterThread=类(TThread)
    私有的
    FDataSet:TClientDataSet;
    //FWriteLock:TMultiReadExclusiveWriteSynchronizer;
    鸥群:TCriticalSection;
    公众的
    构造函数创建(ADataSet:TClientDataSet;ALock:TCriticalSection);
    程序执行;推翻
    结束;
    TDeleterThread=class(TThread)
    私有的
    FDataSet:TClientDataSet;
    //FWriteLock:TMultiReadExclusiveWriteSynchronizer;
    鸥群:TCriticalSection;
    公众的
    构造函数创建(ADataSet:TClientDataSet;ALock:TCriticalSection);
    程序执行;推翻
    结束;
    TForm2=类别(TForm)
    cdsTest:TClientDataSet;
    备忘录1:TMemo;
    CDST编号:TIntegerField;
    按钮1:t按钮;
    TTOMER:TTimer;
    程序按钮1点击(发送方:ToObject);
    程序计时器(发送方:ToObject);
    过程FormClose(发送方:ToObject;var操作:TCloseAction);
    私有的
    {私有声明}
    鸥群:TCriticalSection;
    FWriterThread:TWriterThread;
    FDeleterThread:TDeleterThread;
    程序备忘录;
    公众的
    {公开声明}
    结束;
    变量
    表2:TForm2;
    实施
    {$R*.dfm}
    程序TForm2.按钮1单击(发件人:ToObject);
    开始
    按钮1.已启用:=False;
    cdsTest.CreateDataSet;
    cdsTest.LogChanges:=False;
    FLock:=TCriticalSection.Create;
    tToMemo.Enabled:=真;
    FWriterThread:=TWriterThread.Create(cdsTest,FLock);
    FDeleterThread:=TDeleterThread.Create(cdsTest,FLock);
    结束;
    {TWriterThread}
    构造函数TWriterThread.Create(ADataSet:TClientDataSet;
    ALock:TCriticalSection);
    开始
    继承创建(False);
    FDataSet:=ADataSet;
    羊群:=阿洛克;
    结束;
    过程TWriterThread.Execute;
    变量
    I:整数;
    开始
    继承;
    I:=0;
    虽然没有终止
    开始
    羊群。进入;
    尝试
    公司(一);
    FDataSet.AppendRecord([I]);
    最后
    离开;
    结束;
    睡眠(500)//大约每半秒有一个新记录
    结束;
    结束;
    {TDeleterThread}
    构造函数TDeleterThread.Create(ADataSet:TClientDataSet;
    ALock:TCriticalSection);
    开始
    继承创建(False);
    FDataSet:=ADataSet;
    羊群:=阿洛克;
    结束;
    过程TDeleterThread.Execute;
    常数
    MaxRecords=100;
    变量
    ProcessedRecords:整数;
    开始
    继承;
    虽然没有终止
    开始
    睡眠(3000)//大约每3秒钟删除一次记录
    羊群。进入;
    尝试
    FDataSet.First;
    ProcessedRecords:=0;
    而(不是FDataSet.Eof)和(ProcessedRecords