Sdílet prostřednictvím


Postupy: Zařazování řetězců BSTR pro technologii ADO.NET

Ukazuje, jak přidat řetězec modelu COM (BSTR) do databáze a jak přeuspořádat System.String z databáze na BSTR.

Příklad

V tomto příkladu je třída DatabaseClass vytvořena k vzájemné spolupráci s objektem DataTable technologie ADO.NET. Všimněte si, že tato třída je nativní C++ class (ve srovnání s ref class nebo value class). To je nutné, protože chceme použít tuto třídu z nativního kódu a nemůžeme použít spravované typy v nativním kódu. Tato třída bude kompilována na cílové CLR, jak je označeno direktivou #pragma managed, která předchází deklaraci třídy. Další informace o této direktivě získáte v tématu managed, unmanaged.

Všimněte si soukromého člene třídy DatabaseClass: gcroot<DataTable ^> table. Vzhledem k tomu, že nativní typy nemohou obsahovat spravované typy, klíčové slovo gcroot je nezbytné. Další informace o gcroot naleznete v tématu Postupy: Deklarace popisovačů v Nativních Typech.

Zbytek kódu v tomto příkladu je nativní kód jazyka C++, jak je označeno direktivou #pragma unmanaged, která předchází main. V tomto příkladu vytváříme novou instanci třídy DatabaseClass a voláme její metody, abychom vytvořili tabulku a naplnili některé její řádky. Všimněte si, že řetězce modelu COM jsou předávány jako hodnoty pro sloupec databáze StringCol. Uvnitř DatabaseClass jsou tyto řetězce přeuspořádány na spravované řetězce za použití funkcionality pro uspořádávání, kterou lze nalézt v oboru názvů System.Runtime.InteropServices. Konkrétně metoda PtrToStringBSTR je použita k přeuspořádání BSTR na String a metoda StringToBSTR je použita k přeuspořádání String na BSTR.

Poznámka

Přidělená paměť StringToBSTR musí být uvolněna voláním buď FreeBSTR nebo SysFreeString.

// adonet_marshal_string_bstr.cpp
// compile with: /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll
#include <comdef.h>
#include <gcroot.h>
#include <iostream>
using namespace std;

#using <System.Data.dll>
using namespace System;
using namespace System::Data;
using namespace System::Runtime::InteropServices;

#define MAXCOLS 100

#pragma managed
class DatabaseClass
{
public:
    DatabaseClass() : table(nullptr) { }

    void AddRow(BSTR stringColValue)
    {
        // Add a row to the table.
        DataRow ^row = table->NewRow();
        row["StringCol"] = Marshal::PtrToStringBSTR(
            (IntPtr)stringColValue);
        table->Rows->Add(row);
    }

    void CreateAndPopulateTable()
    {
        // Create a simple DataTable.
        table = gcnew DataTable("SampleTable");

        // Add a column of type String to the table.
        DataColumn ^column1 = gcnew DataColumn("StringCol",
            Type::GetType("System.String"));
        table->Columns->Add(column1);
    }

    int GetValuesForColumn(BSTR dataColumn, BSTR *values,
        int valuesLength)
    {
        // Marshal the name of the column to a managed
        // String.
        String ^columnStr = Marshal::PtrToStringBSTR(
                (IntPtr)dataColumn);

        // Get all rows in the table.
        array<DataRow ^> ^rows = table->Select();
        int len = rows->Length;
        len = (len > valuesLength) ? valuesLength : len;
        for (int i = 0; i < len; i++)
        {
            // Marshal each column value from a managed string
            // to a BSTR.
            values[i] = (BSTR)Marshal::StringToBSTR(
                (String ^)rows[i][columnStr]).ToPointer();
        }

        return len;
    }

private:
    // Using gcroot, you can use a managed type in
    // a native class.
    gcroot<DataTable ^> table;
};

#pragma unmanaged
int main()
{
    // Create a table and add a few rows to it.
    DatabaseClass *db = new DatabaseClass();
    db->CreateAndPopulateTable();

    BSTR str1 = SysAllocString(L"This is string 1.");
    db->AddRow(str1);

    BSTR str2 = SysAllocString(L"This is string 2.");
    db->AddRow(str2);

    // Now retrieve the rows and display their contents.
    BSTR values[MAXCOLS];
    BSTR str3 = SysAllocString(L"StringCol");
    int len = db->GetValuesForColumn(
        str3, values, MAXCOLS);
    for (int i = 0; i < len; i++)
    {
        wcout << "StringCol: " << values[i] << endl;

        // Deallocate the memory allocated using
        // Marshal::StringToBSTR.
        SysFreeString(values[i]);
    }

    SysFreeString(str1);
    SysFreeString(str2);
    SysFreeString(str3);
    delete db;

    return 0;
}
      

Probíhá kompilace kódu

  • Chcete-li zkompilovat kód z příkazového řádku, uložte příklad kódu v souboru s názvem adonet_marshal_string_native.cpp a zadejte následující příkaz:

    cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_native.cpp
    

Zabezpečení

Informace o otázkách zabezpečení zahrnujících technologii ADO.NET naleznete v tématu Securing ADO.NET Applications.

Viz také

Odkaz

System.Runtime.InteropServices

Další zdroje

Přístup k datům za použití technologie ADO.NET v jazyce C++

ADO.NET

Interoperability

Nativní a vzájemná funkční spolupráce rozhraní .NET