Зачем Delphi-коду обновлять поле BLOB-объекта TMYQuery, а затем вылетать? - PullRequest
0 голосов
/ 30 октября 2018

Я пишу запись для инкапсуляции функций чтения и записи полей BLOB-объектов, из файлов или в файлы. Все это в основном работает: я могу назначать BLOB-объекты в новых записях и сохранять файлы из существующих полей BLOB-объектов.

Эта функция обновления блоба из нового файла работает, но вылетает.

procedure TBlobFunction.UpdateRecord(id: int64; const filename: string);
var qry: TDataset;
    blob: TStream;
    fs: TFileStream;
begin
  HourGlass(true);
  qry := DM.CreateQry('SELECT ' + join([blobfield, idfield, filenamefield], ', ')
            +#10' FROM ' + tablename
            +#10'WHERE ' + idfield + ' = ' + id.ToString);
  blob := nil;
  fs := nil;
  try
    qry.Edit;
    qry.FieldByName(filenamefield).AsString := fileName;
    blob := qry.CreateBlobStream(qry.FieldByName(blobfield), bmWrite);
    blob.Seek(0, soFromBeginning);
    fs := TFileStream.Create(fileName, fmOpenRead or fmShareDenyWrite);
    blob.CopyFrom(fs, fs.Size);
    qry.Post;
  finally
    qry.Free;
    fs.Free;
    blob.Free;
  end;
  HourGlass(false);
end{ UpdateRecord};

Этот очень похожий код для создания новой записи работает без сбоев:

function TBlobFunction.NewRecord(const filename: TFilename): int64;
var qry: TDataset;
    blob: TStream;
    fs: TFileStream;
begin
  fs := nil;
  blob := nil;
  qry := DM.CreateQry('SELECT ' + join([blobfield, idfield, filenamefield], ', ') +' FROM ' + tablename + ' LIMIT 0');
  try
    qry.Insert;
    qry.FieldByName(filenamefield).AsString := FileName;
    blob := qry.CreateBlobStream(qry.FieldByName(blobfield), bmWrite);
    blob.Seek(0, soFromBeginning);
    fs := TFileStream.Create(fileName, fmOpenRead or fmShareDenyWrite);
    blob.CopyFrom(fs, fs.Size);
    qry.Post;
    result := qry.FieldByName(idfield).AsLargeInt;
  finally
    fs.Free;
    blob.Free;
    qry.Free;
  end;
end{ NewRecord};

Может кто-нибудь увидеть проблему?

ТИА Mark

1 Ответ

0 голосов
/ 31 октября 2018

Ответ, предоставленный Реми Лебо, состоит в том, чтобы освободить большой двоичный объект до освобождения запроса, от которого он поступил. Я мог бы поместить каждый объект, который нуждался в освобождении, в свой собственный блок try ... finally, но я предпочитаю сохранять код менее загроможденным.

procedure TBlobFunction.UpdateRecord(id: int64; const filename: string);
var qry: TDataset;
    blob: TStream;
    fs: TFileStream;
begin
  HourGlass(true);
  qry := DM.CreateQry('SELECT ' + join([blobfield, idfield, filenamefield], ', ')
            +#10' FROM ' + tablename
            +#10'WHERE ' + idfield + ' = ' + id.ToString);
  blob := nil;
  fs := nil;
  try
    qry.Edit;
    qry.FieldByName(filenamefield).AsString := fileName;
    blob := qry.CreateBlobStream(qry.FieldByName(blobfield), bmWrite);
    blob.Seek(0, soFromBeginning);
    fs := TFileStream.Create(fileName, fmOpenRead or fmShareDenyWrite);
    blob.CopyFrom(fs, fs.Size);
    qry.Post;
  finally
    fs.Free;
    blob.Free;
    qry.Free;
  end;
  HourGlass(false);
end{ UpdateRecord};

Конечно, отказ от сбоев также имеет свои преимущества, но это нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...