Sdílet prostřednictvím


Postupy: Zařazování VARIANT pro ADO.NET

Ukazuje, jak přidat nativní VARIANT do databáze a jak přeuspořádat System.Object z databáze na nativní VARIANT.

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 DatabaseClass a voláme její metody k vytvoření tabulky a naplnění některých řádků tabulky. Všimněte si, že nativní typy VARIANT jsou předávány jako hodnoty pro sloupec databáze ObjectCol. Uvnitř DatabaseClass jsou tyto VARIANT typy přeuspořádány na spravované objekty za použití funkcionality pro uspořádávání, kterou lze nalézt v oboru názvů System.Runtime.InteropServices. Konkrétně metoda GetObjectForNativeVariant je použita k přeuspořádání VARIANT na Object a metoda GetNativeVariantForObject je použita k přeuspořádání Object na 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;
}
      

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_variant.cpp a zadejte následující příkaz:

    cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_variant.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