Filling a Parameter with TParam.LoadFromStream

Discussion of open issues, suggestions and bugs regarding SDAC (SQL Server Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
Deeem2031
Posts: 6
Joined: Wed 08 Jun 2016 13:45

Filling a Parameter with TParam.LoadFromStream

Post by Deeem2031 » Thu 09 Jun 2016 17:39

Hello,

we are currently migrating our codebase from ado to sdac. One of the problems we have encountered has its cause in a procedure that is filling a parameter for a dataset. If you try the following code you'll get an Assertion failure in OLEDBAccess line 3435. If you ignore it an access violation will be raised.
You can fix it by replacing the type of the Fill-Parameter from TParam to TMSParam -> procedure Fill(aParam: TMSParam);
Now this works for this example but isn't a viable solution as not all datasets we use own TMSParams. Besides that the behavior seems to violate the Liskov substitution principle.

Code: Select all

program Project17;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  Winapi.ActiveX,
  Data.DB,
  MSAccess;

var
  qu: TMSQuery;

  procedure Fill(aParam: TParam);
  var
    stream: TMemoryStream;
    bytes: TBytes;
  begin
    stream := TMemoryStream.Create;
    try
      bytes := TEncoding.Unicode.GetBytes('Hello World');
      stream.WriteData(bytes, Length(bytes));
      aParam.LoadFromStream(stream, ftBlob);
    finally
      stream.Free;
    end;
  end;

begin
  CoInitialize(nil);
  try
    qu := TMSQuery.Create(nil);
    try
      qu.Connection := TMSConnection.Create(qu);
      qu.Connection.Server := '';
      qu.Connection.Username := '';
      qu.Connection.Password := '';
      qu.SQL.Text := 'SELECT :param1';
      qu.Prepare;
      Fill(qu.ParamByName('param1'));
      qu.Open;
      Writeln(qu.Fields[0].AsString);
      Readln;
    finally
      qu.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  CoUninitialize;
end.

ViktorV
Devart Team
Posts: 2299
Joined: Wed 30 Jul 2014 07:16

Re: Filling a Parameter with TParam.LoadFromStream

Post by ViktorV » Fri 10 Jun 2016 12:37

The reason for such behavior is that the Virtual directive is not used in the TParam base class in declaration of the LoadFromStream method. Therefore we can't override this method using the Override directive, when declaring it in our TDAParam descendant. You can contact Embarcadero tech support to make them add the Virtual directive to the LoadFromStream method declaration - then you will get the needed behavior. Currently, to work correctly with overridden methods of a variable of the TParam type, you should map it to TMSParam explicitly.

Post Reply