如何使用 unique_ptr 创建 blob 流?

How to create blob stream using unique_ptr?

当使用以下代码时,我成功地将图像保存到“图像”blob 字段中:

if (OpenDialog1->Execute()) {
    ADOTable1->Insert();
    TStream* BlobStream = ADOTable1->CreateBlobStream(ADOTable1->FieldByName("Image"), bmWrite);
    std::unique_ptr<TFileStream> FileStream(new TFileStream(OpenDialog1->FileName, fmOpenRead));
    BlobStream->CopyFrom(FileStream.get(), FileStream->Size);
    delete BlobStream;
    ADOTable1->Post();
}

但是,我也希望使用 std:unique_ptr 创建 BlobStream 对象,这样我就可以避免手动 delete。当我尝试

if (OpenDialog1->Execute()) {
    ADOTable1->Insert();
    std::unique_ptr<TStream> BlobStream(ADOTable1->CreateBlobStream(ADOTable1->FieldByName("Image"), bmWrite));
    std::unique_ptr<TFileStream> FileStream(new TFileStream(OpenDialog1->FileName, fmOpenRead));
    BlobStream->CopyFrom(FileStream.get(), FileStream->Size);
    ADOTable1->Post();
}

我收到 无法插入空行 错误。我在这里做错了什么?我正在使用 C++ Builder 10.3.3。

在原始代码中,您在调用 Post().[=33= 之前 delete 正在 调用 blob TStream 对象 ]

根据 TADOBlobStream 文档:

http://docwiki.embarcadero.com/Libraries/en/Data.Win.ADODB.TADOBlobStream.Destroy

Destroy [ie, the destructor] performs the following tasks:

  • Sets the field's data.

  • Changes the field object's Modified property to true.

  • Triggers a field change event in the field's dataset object.

  • Calls the inherited destructor.

因此,您在 Post() 之前设置了 blob 的字段数据,一切都很好。

在更新的代码中,当 BlobStream 超出范围 调用 Post()。因此,尚未设置字段数据,因此出现错误。

为了确保 blob TStream 对象在调用 Post() 之前被销毁,您可以:

  • BlobStream 周围放置一个新范围:
if (OpenDialog1->Execute()) {
    std::unique_ptr<TFileStream> FileStream(new TFileStream(OpenDialog1->FileName, fmOpenRead));
    ADOTable1->Insert();
    {
    std::unique_ptr<TStream> BlobStream(ADOTable1->CreateBlobStream(ADOTable1->FieldByName("Image"), bmWrite));
    BlobStream->CopyFrom(FileStream.get(), FileStream->Size);
    }
    ADOTable1->Post();
}
  • BlobStream 上手动调用 reset()
if (OpenDialog1->Execute()) {
    std::unique_ptr<TFileStream> FileStream(new TFileStream(OpenDialog1->FileName, fmOpenRead));
    ADOTable1->Insert();
    std::unique_ptr<TStream> BlobStream(ADOTable1->CreateBlobStream(ADOTable1->FieldByName("Image"), bmWrite));
    BlobStream->CopyFrom(FileStream.get(), FileStream->Size);
    BlobStream.reset();
    ADOTable1->Post();
}

无论哪种方式,您都应该进行一些错误处理,以便您可以 Cancel() 插入新行,如果在 Post() 之前发生意外情况,例如:

if (OpenDialog1->Execute()) {
    std::unique_ptr<TFileStream> FileStream(new TFileStream(OpenDialog1->FileName, fmOpenRead));
    ADOTable1->Insert();
    try {
        std::unique_ptr<TStream> BlobStream(ADOTable1->CreateBlobStream(ADOTable1->FieldByName("Image"), bmWrite));
        BlobStream->CopyFrom(FileStream.get(), FileStream->Size);
        BlobStream.reset();
        ADOTable1->Post();
    }
    catch (const Exception &) {
        ADOTable1->Cancel();
        throw;
    }
}