【问题标题】:TClientDataSet error executing with TParam of blob type (ftBlob)使用 blob 类型 (ftBlob) 的 TParam 执行 TClientDataSet 错误
【发布时间】:2016-02-20 11:40:05
【问题描述】:

我们使用的是 MSSQL 2012。

尝试使用存储过程更新客户端照片

spui_SetClientPhoto
int ClientID
VarBinary(Max) Photo

使用纯 ADO 程序运行良好:

ADO.ProcedureName:='spui_SetClientPhoto';
ADO.Parameters.CreateParameter('@ClientsID',ftInteger,pdInput,0,95075);
ADO.Parameters.CreateParameter('@Photo',ftBlob,pdInput,0,NULL);
ADO.Parameters[1].LoadFromFile('C:\Photo.png',ftBlob);
ADO.ExecProc;

但是使用 CDS 会导致错误:

不允许从数据类型 Varchar(max) 到 Varbinary(max) 的隐式转换。

 ADO.ProcedureName:='spui_SetClientPhoto';
 cds.SetProvider(ADO);
 cds.Params.CreateParam(ftInteger,'@ClientsID',ptInput).AsInteger:=95075;
 cds.Params.CreateParam(ftBlob,'@Photo',ptInput).LoadFromFile('C:\Photo.png', ftBlob);
 cds.Execute;

例如无法使用 BLOB 类型的参数运行 CDS。有什么解决办法吗?

【问题讨论】:

  • 你能添加存储过程的 DDL 吗?看他们是否可以在没有它的情况下重现问题是毫无意义的读者。

标签: delphi blob params tclientdataset


【解决方案1】:

以下内容对我来说很好,在 AdoQuery 中使用图片字段类型和 CDS 设置为 ftGraphic,Stored Proc 的 DDL 设置为

CREATE PROCEDURE [dbo].[SetClientPhoto](@ClientID int, @Picture Image)
AS
BEGIN
    SET NOCOUNT ON;
    update table_2 
      set picture = @Picture
    where
      ID = @ClientID
END

代码

procedure TForm1.SavePictureViaStoredProc;
var
  PrvCommandText,
  PrvSql : String;
  ID : Integer;
const
  scTestImage = 'D:\TestPictures\TestBMP.BMP';
begin
  //  First, save the text of the AdoQuery's Sql and the CDS's CommandText
  PrvCommandText := CDS1.CommandText;
  PrvSql := AdoQuery1.SQL.Text;

  //  Save the iD of the row we want to use
  ID := CDS1.FieldByName('ID').AsInteger;
  try
    //  Allow CommandText changes on the DSP
    DataSetProvider1.Options := DataSetProvider1.Options + [poAllowCommandText];
    CDS1.Close;

    // construct a Sql statement to invoke the Stored Proc
    CDS1.CommandText := 'exec dbo.SetClientPhoto @ClientID = :' + IntToStr(ID) + ',  @Picture = :Picture';

    // Set up parameters
    CDS1.Params.Clear;
    CDS1.Params.CreateParam(ftInteger, '@ClientID', ptInput);
    CDS1.Params.CreateParam(ftGraphic, '@Picture', ptInput);
    CDS1.Params.ParamByName('@ClientID').Value := ID;
    CDS1.Params.ParamByName('@Picture').LoadFromFile(scTestImage, ftGraphic);

    AdoQuery1.Close;
    AdoQuery1.SQL.Text := '';
    CDS1.Execute;  // This executes the stored proc
    CDS1.Params.Clear;
  finally
    ADoQuery1.SQL.Text := PrvSql;
    CDS1.CommandText := PrvCommandText;
    CDS1.Open;
  end;

end;

注意:我很少将图像存储在数据库中,并且还没有设法使其与 .Jpg 和 .Png 文件一起使用。我隐约记得,将它们存储在数据库中需要一个额外的步骤,而不会出现“流读取错误”或“无效图像”异常,我会看看我是否可以稍后提醒自己。

【讨论】:

  • 感谢您的回复。但是您将其作为简单的 SQL 查询执行,而不是作为存储过程。我们的解决方案是将二进制编码为Base64,发送到服务器将其编码回二进制并保存
  • “但是你正在执行这个作为简单的 SQL 查询,而不是作为存储过程”不知道你的意思 - 我在该代码中所做的全部重点是设置 CDS 的 CommandText 来调用通过 AdoQuery 将存储过程存储在服务器上。如果你想要一些不同的东西,你最好在你的 q 中清楚地说明你确实想要什么。
猜你喜欢
  • 2019-11-22
  • 1970-01-01
  • 2023-03-04
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多