无法使用datasnap客户端进行插入

时间:2014-07-21 21:55:46

标签: delphi datasnap

我正在尝试使用datasnap(之前从未使用过它)并遇到了一个奇怪的问题。 也许我做错了,我不知道。 我在表单上放了一个Clientdataset3。将它链接到SQLConnection1(在同一表格上) 哪个连接到datasnap服务器。 我还将Clientdataset3链接到服务器端的datasetprovider(允许命令文本) 链接到我要插入的表。但是当我跑步时:

procedure TForm3.AdvGlowButton1Click(Sender: TObject);
begin
clientdataset3.CommandText:='insert into "MY_TABLE" (twit) values (:A)';
clientdataset3.Params.ParamByName('A').AsString := cxmemo1.Lines.Text;
clientdataset3.Execute;
end;

我得到"远程错误:没有这样的表:插入"

我做错了什么?数据库是通过DBX的SQLite,使用XE6。

1 个答案:

答案 0 :(得分:1)

如果您使用SELECT语句填充CDS,则无需执行发送定制INSERT语句的练习。

您应该可以致电

ClientDataSet3.Insert;
// populate fields here
ClientDataSet3.Post;

然后调用ClientDataSet3.ApplyUpdates。

同样,您只需调用ClientDataSet3.Delete即可执行DELETE。

必要的INSERT,DELETE和UPDATE语句的构造由CDS的提供者处理。但是,我并不打算建议您无法按照您尝试的方式执行INSERT - 它应该可以正常工作。

我无法从这里告诉你INSERT出了什么问题,所以相反,这里有一些适合我的代码(包括CREATE TABLE,etc语句),所以你可以& #34;发现差异。"我在2014年6月4日的Win7 64位和sqlite3.dll v.3.8.5.0上使用了XE6。

示例代码提供了执行插入的3种方式(全部检查和工作),两种使用自定义INSERT语句,第三种使用CDS的默认插入行为,可以在代码(CDS1.Insert)中调用点击' +' DBNavigator上的按钮。默认的CDS插入行为需要特殊处理:尽管服务器上的ID列定义为Autoinc,但在执行CDS插入时获取autoinc值是有问题的,因此代码使用此处描述的方法:

http://edn.embarcadero.com/article/20847

生成临时的否定ID值,该值在CDS ApplyUpdates过程中被替换。请注意,DFM中有关SqlQuery ID字段中有关ProviderFlags的链接的勘误部分中引用的度量是必需的,因为服务器上的ID列值是64位整数。

type
  TDataOperation = (doCreateTable, doDropTable, doInsert, doInsertUsingParams, doSelect);

TForm3 = class(TForm)
[...]
{ private declarations }
  ID : Int64;
  function NextID : Int64;
[...]
end;

implementation

{$R *.dfm}

const
  scCreateTable = 'CREATE TABLE [MATable2] ([ID] INTEGER NOT NULL '
    + #13#10 + 'PRIMARY KEY AUTOINCREMENT,  [AName] VARCHAR(20), '
    + #13#10 + '  [AMemo] MEMO)';

  scDropTable =
    'DROP TABLE [MATable2]';

  scInsert1 =
    'INSERT INTO [MATable2] (AName, AMemo) VALUES(''a'', ''A memo'')';

  scSelect =
    'SELECT * FROM [MATable2]';

  scInsertUsingParams =
    'INSERT INTO [MATable2] (AName, AMemo) VALUES(:AName, :AMemo)';

procedure TForm3.PerformTableOperation(Operation : TDataOperation);
var
  Param : TParam;
begin
  if {(Operation in [toCreate, toDrop]) and} CDS1.Active then
    CDS1.Close;
  case Operation of
    doCreateTable : begin
      CDS1.CommandText := scCreateTable;
      CDS1.Execute;
      PerformTableOperation(doSelect);
    end;
    doDropTable : begin
      CDS1.CommandText := scDropTable;
      CDS1.Execute;
    end;
    doSelect : begin
      CDS1.CommandText := scSelect;
      CDS1.Open;
    end;
    doInsert : begin
      CDS1.CommandText := scInsert1;
      CDS1.Execute;
      PerformTableOperation(doSelect);
    end;
    doInsertUsingParams : begin

      CDS1.CommandText := scInsertUsingParams;
//      CDS1.FetchParams;
      CDS1.Params.ParamByName('AName').AsString:= 'bcdef';
      CDS1.Params.ParamByName('AMemo').AsString := 'memo b';
      CDS1.Execute;
      CDS1.Params.Clear;

      PerformTableOperation(doSelect);
    end;
  end;
  if CDS1.Active then  // it won't be  after a toDrop
    CDS1.ApplyUpdates(-1);
end;


procedure TForm3.OpenConnection;
begin
 SqlConnection1.Open;
end;

procedure TForm3.btnCreateClick(Sender: TObject);
begin
  PerformTableOperation(doCreateTable);
end;

[etc ...]

procedure TForm3.btnReopenClick(Sender: TObject);
begin
  CDS1.Close;
  PerformTableOperation(doSelect);
end;

procedure TForm3.btnSelectClick(Sender: TObject);
begin
  PerformTableOperation(doSelect);
end;

procedure TForm3.CDS1AfterDelete(DataSet: TDataSet);
begin
  CDS1.ApplyUpdates(-1);
end;

procedure TForm3.CDS1AfterPost(DataSet: TDataSet);
begin
  CDS1.ApplyUpdates(-1);
end;

procedure TForm3.CDS1NewRecord(DataSet: TDataSet);
begin
  CDS1.FieldByName('ID').AsInteger := NextID;
end;

function TForm3.NextID: Int64;
begin
  Dec(ID);
  Result := ID;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  OpenConnection;
end;

end.

这是一个部分DFM,可以最大限度地减少猜测我的数据库组件设置方式的必要性。

object Form3: TForm3
[...]
  object DBGrid1: TDBGrid
    Left = 8
    Top = 8
    Width = 456
    Height = 193
    DataSource = DataSource1
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
    Columns = <
      item
        Expanded = False
        FieldName = 'ID'
        Visible = True
      end
      item
        Expanded = False
        FieldName = 'AName'
        Visible = True
      end
      item
        Expanded = False
        FieldName = 'AMemo'
        Visible = True
      end>
  end
  [...]
  object DBNavigator1: TDBNavigator
    Left = 16
    Top = 216
    Width = 240
    Height = 25
    DataSource = DataSource1
    TabOrder = 6
  end
  object DBMemo1: TDBMemo
    Left = 207
    Top = 259
    Width = 185
    Height = 74
    DataField = 'AMemo'
    DataSource = DataSource1
    TabOrder = 7
  end
  object DBEdit1: TDBEdit
    Left = 24
    Top = 264
    Width = 121
    Height = 21
    DataField = 'AName'
    DataSource = DataSource1
    TabOrder = 8
  end
  object SQLConnection1: TSQLConnection
    ConnectionName = 'SQLITECONNECTION'
    DriverName = 'Sqlite'
    LoginPrompt = False
    Params.Strings = (
      'DriverName=Sqlite'
      'Database=D:\delphi\xe6\sqlite\matestdb.sqlite')
    Connected = True
    Left = 40
    Top = 16
  end
  object SQLQuery1: TSQLQuery
    MaxBlobSize = 1
    Params = <>
    SQL.Strings = (
      'select * from [matable2]')
    SQLConnection = SQLConnection1
    Left = 128
    Top = 16
    object SQLQuery1ID: TLargeintField
      FieldName = 'ID'
      ProviderFlags = [pfInWhere, pfInKey]
    end
    object SQLQuery1AName: TWideStringField
      FieldName = 'AName'
    end
    object SQLQuery1AMemo: TWideMemoField
      FieldName = 'AMemo'
      BlobType = ftWideMemo
      Size = 1
    end
  end
  object DataSetProvider1: TDataSetProvider
    DataSet = SQLQuery1
    Options = [poAllowCommandText, poUseQuoteChar]
    UpdateMode = upWhereKeyOnly
    Left = 216
    Top = 16
  end
  object CDS1: TClientDataSet
    Aggregates = <>
    CommandText = 'select * from MATable2'
    Params = <>
    ProviderName = 'DataSetProvider1'
    BeforeInsert = CDS1BeforeInsert
    AfterInsert = CDS1AfterInsert
    BeforePost = CDS1BeforePost
    AfterPost = CDS1AfterPost
    AfterDelete = CDS1AfterDelete
    OnNewRecord = CDS1NewRecord
    AfterApplyUpdates = CDS1AfterApplyUpdates
    Left = 288
    Top = 16
    object CDS1ID: TLargeintField
      FieldName = 'ID'
    end
    object CDS1AName: TWideStringField
      FieldName = 'AName'
    end
    object CDS1AMemo: TWideMemoField
      FieldName = 'AMemo'
      BlobType = ftWideMemo
      Size = 1
    end
  end
  object DataSource1: TDataSource
    DataSet = CDS1
    Left = 344
    Top = 16
  end
end