Aracılığıyla paylaş


ADO.NET için SAFEARRAY Nasıl Hazırlanır

Bir veritabanına nasıl yerelSAFEARRAY ekleneceğini ve veritabanından yerel bir SAFEARRAY üzerine nasıl yönetilen dize sıralaması yapacağınızı gösterir.

Örnek

Bu örnekte, ADO.NET DataTable nesnesiyle etkileşimde bulunabilmek için DatabaseClass sınıfı oluşturuldu. Bu sınıfın yerel C++ class'ı (ref class'a veya value class'a kıyasla) olduğunu unutmayın. Bu sınıfı yerel koddan kullanmak istediğimizden ve yerel kodda yönetilen türleri kullanamayacağınızdan dolayı bu gereklidir. Sınıf bildiriminden önceki #pragma managed yönergesinde de belirtildiği gibi bu sınıf hedef CLR için derlenecektir. Bu yönergeyle ilgili daha fazla bilgi için bkz. managed, unmanaged.

DatabaseClass sınıfının özel üyesine dikkat edin: gcroot<DataTable ^> table. Yerel türler yönetilen türleri içeremediğinden gcroot anahtar sözcüğü gereklidir. gcroot hakkında daha fazla bilgi için, bkz. Yerel Türlerde İşleyiciler Nasıl Bildirilir.

main'den önce gelen #pragma unmanaged yönergesinde de belirtildiği gibi bu örnekteki kodun kalan kısmı yerel C++ kodudur. Bu örnekte, DatabaseClass'ının yeni olgusunu oluşturacağız ve tablo oluşturup tablonun bazı satırlarını doldurmak için DatabaseClass'ın yöntemlerini çağıracağız. Yerel SAFEARRAY türlerinin ArrayIntsCol veri sütunu için değer olarak geçirildiğini unutmayın. DatabaseClass'ında bu SAFEARRAY türler System.Runtime.InteropServices ad uzayındaki hazırlama işlevi kullanılarak yönetilen nesneler için hazırlanır. Özellikle, Copy yöntemi yönetilen tamsayı dizisine bir SAFEARRAY sıralamak için kullanılır ve Copy yöntemi bir SAFEARRAY öğesine bir yönetilen tamsayı dizesi sı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;
}
  

Kodu Derleme

  • Kodu komut satırından derlemek için, 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
    

Güvenlik

ADO.NET'i ilgilendiren güvenlik sorunlarıyla ilgili bilgi için, bkz. Securing ADO.NET Applications.

Ayrıca bkz.

Başvuru

System.Runtime.InteropServices

Diğer Kaynaklar

C++'ta ADO.NET Kullanarak Veri Erişimi

ADO.NET

Birlikte çalışabilirlik

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