Aracılığıyla paylaş


ADO.NET Kullanarak Veri Erişimi (C++/CLI)

ADO.NET, veri erişimi için .NET Framework API'dir ve önceki veri erişim çözümleriyle eşleşmeyen güç ve kullanım kolaylığı sağlar. Bu bölümde, yerel türleri hazırlama gibi Visual C++ kullanıcılarına özgü ADO.NET ile ilgili bazı sorunlar açıklanmaktadır.

ADO.NET Ortak Dil Çalışma Zamanı (CLR) altında çalışır. Bu nedenle, ADO.NET ile etkileşim kuran tüm uygulamalar da CLR'yi hedeflemelidir. Ancak bu, yerel uygulamaların ADO.NET kullanamayacağı anlamına gelmez. Bu örnekler, yerel koddan bir ADO.NET veritabanıyla nasıl etkileşim kurulacağını gösterir.

ansi dizelerini ADO.NET için hazırlama

Veritabanına yerel dize (char *) eklemeyi ve veritabanından yerel dizeye nasıl sıralamayı System.String gösterir.

Örnek

Bu örnekte DatabaseClass sınıfı bir ADO.NET DataTable nesnesiyle etkileşim kurmak için oluşturulmuştur. Bu sınıfın yerel bir C++ class olduğunu unutmayın (veya value classile karşılaştırıldığındaref class). Bu sınıfı yerel koddan kullanmak istediğimiz ve yönetilen türleri yerel kodda kullanamayacağınız için bu gereklidir. Bu sınıf, sınıf bildiriminden önceki yönerge tarafından gösterildiği gibi CLR'yi #pragma managed hedeflemek için derlenir. Bu yönerge hakkında daha fazla bilgi için bkz . yönetilen, yönetilmeyen.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türler içeremediğinden gcroot anahtar sözcüğü gereklidir. hakkında gcrootdaha fazla bilgi için bkz . Nasıl yapılır: Yerel Türlerde Tanıtıcıları Bildirme.

Bu örnekteki kodun geri kalanı yerel C++ kodudur ve önceki mainyönergesinde #pragma unmanaged de belirtilmiştir. Bu örnekte, yeni bir DatabaseClass örneği oluşturup tablo oluşturmak ve tablodaki bazı satırları doldurmak için yöntemlerini çağırıyoruz. Yerel C++ dizelerinin StringCol veritabanı sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass içinde, bu dizeler ad alanında System.Runtime.InteropServices bulunan sıralama işlevselliği kullanılarak yönetilen dizelere sıralanır. Özellikle, yöntemi PtrToStringAnsi için bir char * sıralamak için Stringkullanılır ve yöntemi StringToHGlobalAnsi bir için sıralamak String için char *kullanılır.

Dekont

tarafından StringToHGlobalAnsi ayrılan bellek veya GlobalFreeçağrılarak FreeHGlobal serbest bırakılmalıdır.

// adonet_marshal_string_native.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(char *stringColValue)
    {
        // Add a row to the table.
        DataRow ^row = table->NewRow();
        row["StringCol"] = Marshal::PtrToStringAnsi(
            (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(char *dataColumn, char **values,
        int valuesLength)
    {
        // Marshal the name of the column to a managed
        // String.
        String ^columnStr = Marshal::PtrToStringAnsi(
                (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 char *.
            values[i] = (char *)Marshal::StringToHGlobalAnsi(
                (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();
    db->AddRow("This is string 1.");
    db->AddRow("This is string 2.");

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

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

    delete db;

    return 0;
}
StringCol: This is string 1.
StringCol: This is string 2.

Kod Derleniyor

  • Kodu komut satırından derlemek için kod örneğini adonet_marshal_string_native.cpp adlı bir dosyaya kaydedin ve aşağıdaki deyimi girin:

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

ADO.NET için BSTR Dizelerini Hazırlama

Veritabanına COM dizesi (BSTR) eklemeyi ve veritabanından 'a sıralamayı System.StringBSTRgösterir.

Örnek

Bu örnekte DatabaseClass sınıfı bir ADO.NET DataTable nesnesiyle etkileşim kurmak için oluşturulmuştur. Bu sınıfın yerel bir C++ class olduğunu unutmayın (veya value classile karşılaştırıldığındaref class). Bu sınıfı yerel koddan kullanmak istediğimiz ve yönetilen türleri yerel kodda kullanamayacağınız için bu gereklidir. Bu sınıf, sınıf bildiriminden önceki yönerge tarafından gösterildiği gibi CLR'yi #pragma managed hedeflemek için derlenir. Bu yönerge hakkında daha fazla bilgi için bkz . yönetilen, yönetilmeyen.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türler içeremediğinden gcroot anahtar sözcüğü gereklidir. hakkında gcrootdaha fazla bilgi için bkz . Nasıl yapılır: Yerel Türlerde Tanıtıcıları Bildirme.

Bu örnekteki kodun geri kalanı yerel C++ kodudur ve önceki mainyönergesinde #pragma unmanaged de belirtilmiştir. Bu örnekte, yeni bir DatabaseClass örneği oluşturup tablo oluşturmak ve tablodaki bazı satırları doldurmak için yöntemlerini çağırıyoruz. COM dizelerinin StringCol veritabanı sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass içinde, bu dizeler ad alanında System.Runtime.InteropServices bulunan sıralama işlevselliği kullanılarak yönetilen dizelere sıralanır. Özellikle, yöntemi PtrToStringBSTR için bir BSTR sıralamak için Stringkullanılır ve yöntemi StringToBSTR bir için sıralamak String için BSTRkullanılır.

Dekont

tarafından StringToBSTR ayrılan bellek veya SysFreeStringçağrılarak FreeBSTR serbest bırakılmalıdır.

// 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;
}
StringCol: This is string 1.
StringCol: This is string 2.

Kod Derleniyor

  • Kodu komut satırından derlemek için kod örneğini adonet_marshal_string_native.cpp adlı bir dosyaya kaydedin ve aşağıdaki deyimi girin:

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

ADO.NET için Unicode Dizelerini Hazırlama

Veritabanına yerel Unicode dizesi (wchar_t *) eklemeyi ve veritabanından yerel Unicode dizesine nasıl sıralamayı System.String gösterir.

Örnek

Bu örnekte DatabaseClass sınıfı bir ADO.NET DataTable nesnesiyle etkileşim kurmak için oluşturulmuştur. Bu sınıfın yerel bir C++ class olduğunu unutmayın (veya value classile karşılaştırıldığındaref class). Bu sınıfı yerel koddan kullanmak istediğimiz ve yönetilen türleri yerel kodda kullanamayacağınız için bu gereklidir. Bu sınıf, sınıf bildiriminden önceki yönerge tarafından gösterildiği gibi CLR'yi #pragma managed hedeflemek için derlenir. Bu yönerge hakkında daha fazla bilgi için bkz . yönetilen, yönetilmeyen.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türler içeremediğinden gcroot anahtar sözcüğü gereklidir. hakkında gcrootdaha fazla bilgi için bkz . Nasıl yapılır: Yerel Türlerde Tanıtıcıları Bildirme.

Bu örnekteki kodun geri kalanı yerel C++ kodudur ve önceki mainyönergesinde #pragma unmanaged de belirtilmiştir. Bu örnekte, yeni bir DatabaseClass örneği oluşturup tablo oluşturmak ve tablodaki bazı satırları doldurmak için yöntemlerini çağırıyoruz. Unicode C++ dizelerinin StringCol veritabanı sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass içinde, bu dizeler ad alanında System.Runtime.InteropServices bulunan sıralama işlevselliği kullanılarak yönetilen dizelere sıralanır. Özellikle, yöntemi PtrToStringUni için bir wchar_t * sıralamak için Stringkullanılır ve yöntemi StringToHGlobalUni bir için sıralamak String için wchar_t *kullanılır.

Dekont

tarafından StringToHGlobalUni ayrılan bellek veya GlobalFreeçağrılarak FreeHGlobal serbest bırakılmalıdır.

// adonet_marshal_string_wide.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(wchar_t *stringColValue)
    {
        // Add a row to the table.
        DataRow ^row = table->NewRow();
        row["StringCol"] = Marshal::PtrToStringUni(
            (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(wchar_t *dataColumn, wchar_t **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 string
            // to a wchar_t *.
            values[i] = (wchar_t *)Marshal::StringToHGlobalUni(
                (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();
    db->AddRow(L"This is string 1.");
    db->AddRow(L"This is string 2.");

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

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

    delete db;

    return 0;
}
StringCol: This is string 1.
StringCol: This is string 2.

Kod Derleniyor

  • Kodu komut satırından derlemek için kod örneğini adonet_marshal_string_wide.cpp adlı bir dosyaya kaydedin ve aşağıdaki deyimi girin:

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

ADO.NET için VARIANT hazırlama

Veritabanına yerel VARIANT ekleme ve veritabanından VARIANTyerel bir öğesine nasıl sıralama System.Object yapılacağını gösterir.

Örnek

Bu örnekte DatabaseClass sınıfı bir ADO.NET DataTable nesnesiyle etkileşim kurmak için oluşturulmuştur. Bu sınıfın yerel bir C++ class olduğunu unutmayın (veya value classile karşılaştırıldığındaref class). Bu sınıfı yerel koddan kullanmak istediğimiz ve yönetilen türleri yerel kodda kullanamayacağınız için bu gereklidir. Bu sınıf, sınıf bildiriminden önceki yönerge tarafından gösterildiği gibi CLR'yi #pragma managed hedeflemek için derlenir. Bu yönerge hakkında daha fazla bilgi için bkz . yönetilen, yönetilmeyen.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türler içeremediğinden gcroot anahtar sözcüğü gereklidir. hakkında gcrootdaha fazla bilgi için bkz . Nasıl yapılır: Yerel Türlerde Tanıtıcıları Bildirme.

Bu örnekteki kodun geri kalanı yerel C++ kodudur ve önceki mainyönergesinde #pragma unmanaged de belirtilmiştir. Bu örnekte, yeni bir DatabaseClass örneği oluşturup tablo oluşturmak ve tablodaki bazı satırları doldurmak için yöntemlerini çağırıyoruz. Yerel VARIANT türlerin ObjectCol veritabanı sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass içinde, bu VARIANT türler ad alanında bulunan hazırlama işlevselliği kullanılarak yönetilen nesnelere System.Runtime.InteropServices sıralanır. Özellikle, yöntemi GetObjectForNativeVariant için bir VARIANT sıralamak için Objectkullanılır ve yöntemi GetNativeVariantForObject bir için sıralamak Object için VARIANTkullanılır.

// 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

Kod Derleniyor

  • Kodu komut satırından derlemek için kod örneğini adonet_marshal_variant.cpp adlı bir dosyaya kaydedin ve aşağıdaki deyimi girin:

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

ADO.NET için SAFEARRAY hazırlama

Veritabanına yerel SAFEARRAY bir dizinin nasıl ekleneceğini ve bir veritabanından SAFEARRAYyerel bir dizinin nasıl sıraleneceğini gösterir.

Örnek

Bu örnekte DatabaseClass sınıfı bir ADO.NET DataTable nesnesiyle etkileşim kurmak için oluşturulmuştur. Bu sınıfın yerel bir C++ class olduğunu unutmayın (veya value classile karşılaştırıldığındaref class). Bu sınıfı yerel koddan kullanmak istediğimiz ve yönetilen türleri yerel kodda kullanamayacağınız için bu gereklidir. Bu sınıf, sınıf bildiriminden önceki yönerge tarafından gösterildiği gibi CLR'yi #pragma managed hedeflemek için derlenir. Bu yönerge hakkında daha fazla bilgi için bkz . yönetilen, yönetilmeyen.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türler içeremediğinden gcroot anahtar sözcüğü gereklidir. hakkında gcrootdaha fazla bilgi için bkz . Nasıl yapılır: Yerel Türlerde Tanıtıcıları Bildirme.

Bu örnekteki kodun geri kalanı yerel C++ kodudur ve önceki mainyönergesinde #pragma unmanaged de belirtilmiştir. Bu örnekte, yeni bir DatabaseClass örneği oluşturup tablo oluşturmak ve tablodaki bazı satırları doldurmak için yöntemlerini çağırıyoruz. Yerel SAFEARRAY türlerin ArrayIntsCol veritabanı sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass içinde, bu SAFEARRAY türler ad alanında bulunan hazırlama işlevselliği kullanılarak yönetilen nesnelere System.Runtime.InteropServices sıralanır. Özellikle, yöntemi Copy yönetilen bir tamsayı dizisine sıralamak SAFEARRAY için kullanılır ve yöntemi Copy yönetilen bir tamsayı dizisini olarak SAFEARRAYsıralamak için kullanılır.

// adonet_marshal_safearray.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(SAFEARRAY *arrayIntsColValue)
    {
        // Add a row to the table.
        DataRow ^row = table->NewRow();
        int len = arrayIntsColValue->rgsabound[0].cElements;
        array<int> ^arr = gcnew array<int>(len);

        int *pData;
        SafeArrayAccessData(arrayIntsColValue, (void **)&pData);
        Marshal::Copy(IntPtr(pData), arr, 0, len);
        SafeArrayUnaccessData(arrayIntsColValue);

        row["ArrayIntsCol"] = arr;
        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("ArrayIntsCol",
            Type::GetType("System.Int32[]"));
        table->Columns->Add(column1);
    }

    int GetValuesForColumn(wchar_t *dataColumn, SAFEARRAY **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 array
            // of Int32s to a SAFEARRAY of type VT_I4.
            values[i] = SafeArrayCreateVector(VT_I4, 0, 10);
            int *pData;
            SafeArrayAccessData(values[i], (void **)&pData);
            Marshal::Copy((array<int> ^)rows[i][columnStr], 0,
                IntPtr(pData), 10);
            SafeArrayUnaccessData(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();

    // Create a standard array.
    int originalArray[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    // Create a SAFEARRAY.
    SAFEARRAY *psa;
    psa = SafeArrayCreateVector(VT_I4, 0, 10);

    // Copy the data from the original array to the SAFEARRAY.
    int *pData;
    HRESULT hr = SafeArrayAccessData(psa, (void **)&pData);
    memcpy(pData, &originalArray, 40);
    SafeArrayUnaccessData(psa);
    db->AddRow(psa);

    // Now retrieve the rows and display their contents.
    SAFEARRAY *values[MAXCOLS];
    int len = db->GetValuesForColumn(
        L"ArrayIntsCol", values, MAXCOLS);
    for (int i = 0; i < len; i++)
    {
        int *pData;
        SafeArrayAccessData(values[i], (void **)&pData);
        for (int j = 0; j < 10; j++)
        {
            cout << pData[j] << " ";
        }
        cout << endl;
        SafeArrayUnaccessData(values[i]);

        // Deallocate the memory allocated using
        // SafeArrayCreateVector.
        SafeArrayDestroy(values[i]);
    }

    SafeArrayDestroy(psa);
    delete db;

    return 0;
}
0 1 2 3 4 5 6 7 8 9

Kod Derleniyor

  • Kodu komut satırından derlemek için kod örneğini adonet_marshal_safearray.cpp adlı bir dosyaya kaydedin ve aşağıdaki deyimi girin:

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

.NET Framework Güvenliği

ADO.NET ile ilgili güvenlik sorunları hakkında bilgi için bkz . ADO.NET Uygulamalarının Güvenliğini Sağlama.

Bölüm Tanım
ADO.NET .NET programcısının veri erişim hizmetlerini kullanıma sunan bir sınıf kümesi olan ADO.NET genel bakış sağlar.

Ayrıca bkz.

C++/CLI (Visual C++) ile .NET Programlama

Yerel ve.NET Birlikte Çalışabilirliği

System.Runtime.InteropServices

Birlikte çalışabilirlik