Como: realizar realizar marshaling um VARIANT para o ADO.NET

Demonstra como adicionar um nativo VARIANT para um banco de dados e como realizar realizar marshaling um System.Object de um banco de dados para um nativo VARIANT.

Exemplo

Neste exemplo, a classe DatabaseClass é criada para interagir com um ADO.NET DataTable objeto. Observe que este clsistema autônomos é um C++ nativo class (sistema autônomo em comparação com um ref class ou value class). Isso é necessário porque queremos usar essa classe de código nativo e não é possível usar tipos gerenciado em código nativo.Este clsistema autônomos será ser compilado para direcionar o CLR sistema autônomo é indicado pelo #pragma managed diretiva antecedendo a declaração clsistema autônomos. Para obter mais informações sobre essa diretiva, consulte gerenciado, não gerenciado.

Observe o membro particular da classe DatabaseClass: gcroot<DataTable ^> table.Como tipos nativo não podem conter tipos gerenciado, a gcroot palavra-chave é necessária. Para obter mais informações sobre gcroot, consulte: Como: Declarar Handles em tipos nativo.

O restante do código no exemplo é o código C++ nativo, conforme indicado pelo #pragma unmanaged diretiva anterior main. Neste exemplo, estamos criando uma nova instância de DatabaseClass e chamando seus métodos para criar uma tabela e popular algumas linhas da tabela.Observe que nativo VARIANT tipos estão sendo passados sistema autônomo valores da coluna do banco de dados ObjectCol. DatabaseClass Inside, esses VARIANT tipos são empacotados para objetos gerenciado usando a funcionalidade de marshaling encontrada na System.Runtime.InteropServices espaço para nome. Especificamente, o método GetObjectForNativeVariant usado para realizar realizar marshaling uma VARIANT para um Objecte o método GetNativeVariantForObject usado para realizar realizar marshaling uma Object para um VARIANT.

// adonet_marshal_variant.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(VARIANT *objectColValue)
    {
        // Add a row to the table.
        DataRow ^row = table->NewRow();
        row["ObjectCol"] = Marshal::GetObjectForNativeVariant(
            IntPtr(objectColValue));
        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("ObjectCol",
            Type::GetType("System.Object"));
        table->Columns->Add(column1);
    }

    int GetValuesForColumn(wchar_t *dataColumn, VARIANT *values,
        int valuesLength)
    {
        // Marshal the name of the column to a managed
        // String.
        String ^columnStr = Marshal::PtrToStringUni(
                (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 object
            // to a VARIANT.
            Marshal::GetNativeVariantForObject(
                rows[i][columnStr], IntPtr(&values[i]));
        }

        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 bstr1 = SysAllocString(L"This is a BSTR in a VARIANT.");
    VARIANT v1;
    v1.vt = VT_BSTR;
    v1.bstrVal = bstr1;
    db->AddRow(&v1);

    int i = 42;
    VARIANT v2;
    v2.vt = VT_I4;
    v2.lVal = i;
    db->AddRow(&v2);

    // Now retrieve the rows and display their contents.
    VARIANT values[MAXCOLS];
    int len = db->GetValuesForColumn(
        L"ObjectCol", values, MAXCOLS);
    for (int i = 0; i < len; i++)
    {
        switch (values[i].vt)
        {
            case VT_BSTR:
                wcout << L"ObjectCol: " << values[i].bstrVal << endl;
                break;
            case VT_I4:
                cout << "ObjectCol: " << values[i].lVal << endl;
                break;
            default:
                break;
        }

    }

    SysFreeString(bstr1);
    delete db;

    return 0;
}

ObjectCol: This is a BSTR in a VARIANT. ObjectCol: 42

Compilando o código

  • Para compilar o código a partir da linha de comando, salvar o exemplo de código em um arquivo chamado adonet_marshal_variant.cpp e insira a demonstrativo a seguir:

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

Segurança

Para obter informações sobre questões de segurança envolvendo o ADO.NET, consulte Protegendo aplicativos do ADO.NET.

Consulte também

Referência

System.Runtime.InteropServices

Outros recursos

Acesso de dados usando ADO.NET em C++

ADO.NET

Interoperabilidade

Nativo e interoperabilidade .NET