Davide Rubbiani wrote:
Davide Rubbiani wrote:
// TFDParam.AsStream returns reference to internal low-level
stream QryFS.Params.ParamByName('st').AsStream.Read(Buffer,
Length(Buffer)); <------ Here I get an Access violation
From your code you're not initializing the buffer:
SetLength(buffer, QryFS.Params.ParamByName('st').asStream.SIZE);
prior to:
QryFS.Params.ParamByName('st').AsStream.Read(Buffer,
Length(Buffer));
Hello Lajos,
thanks for your response.
Unfortunately your indication did not solve the problem.
Now I get the access violation exception on the line that sets the
buffer size. It seems the problem is on the "st" params which seems
not assigned.
I try with a fresh new database but i got the same exception.
Is there a way to check if the "st" params is correctly assigned?
Thank you,
Davide
Try to debug using debug dcu. This code should work.
Hello,
after a lot of test I can't still read any filestream field form my MS SQL 2014 database.
The error is Always an "Access violation" on the line that sets the buffer size.
In fact the Params[0] seems to be nil.
Following the code I'm using to write and read single record to my filestream table :
function TDataModule2.LoadAttachment(const ASerialNo: Integer): TStream;
var
QryFS: TFDQuery;
Buffer: TArray<System.Byte>;
begin
QryFS := TFDQuery.Create(nil);
QryFS.Connection := Connection;
try
Connection.StartTransaction;
try
QryFS.SQL.Text := 'select :st = Chart.PathName() from Records where SerialNumber = :id';
QryFS.Params[0].DataType := ftStream;
QryFS.Params[0].FDDataType := dtHBFile;
QryFS.Params[0].ParamType := ptOutput;
QryFS.Params[0].StreamMode := smOpenRead;
QryFS.Params[1].AsInteger := ASerialNo;
QryFS.OpenOrExecute;
// TFDParam.AsStream returns reference to internal low-level stream
SetLength(Buffer, QryFS.Params[0].AsStream.Size);
QryFS.Params[0].AsStream.Read(Buffer, Length(Buffer));
Result := QryFS.Params[0].AsStream;
Connection.Commit;
except
Connection.Rollback;
raise;
end;
finally
QryFS.Free;
end;
end;
procedure TDataModule2.StoreAttachment(const ASerialNo: Integer; const AFileName: string);
var
oStr: TFileStream;
FName: string;
QryFS: TFDQuery;
begin
QryFS := TFDQuery.Create(nil);
QryFS.Connection := Connection;
try
Connection.StartTransaction;
try
QryFS.SQL.Text := 'INSERT INTO [dbo].[Records] ([SerialNumber], [Chart]) VALUES (:SerialNumber, :Chart)';
QryFS.Params[0].Value := ASerialNo;
QryFS.Params[1].DataType := ftStream;
QryFS.Params[1].StreamMode := smOpenWrite;
QryFS.ExecSQL;
oStr := TFileStream.Create(AFileName, fmOpenRead);
try
// FireDAC receives a copy of the stream
QryFS.Params[1].AsStream.CopyFrom(oStr, -1);
finally
// The user is responsible for freeing the original stream
oStr.Free;
end;
QryFS.CloseStreams;
Connection.Commit;
except
Connection.Rollback;
raise;
end;
finally
QryFS.Free
end;
end;
Selecting rows from smss query results in a correct number and valued records (comprise the .PathName() function) so the writing procedure seems to work fine.
Unfortunately FILESTREAM seems the right choice to respond to my application requisites.
Have you got any advice about make the above code functioning? (or a functioning sample I can run on my side)
Thank you,
Davide
Edited by: Davide Rubbiani on Sep 11, 2017 9:19 AM
Connect with Us