Jak: MARSZAŁEK SAFEARRAY dla obiektów ADO.NET (C + +/ CLI)
Przedstawia sposób dodawania macierzystego SAFEARRAY do bazy danych i sposobu zorganizowania tablicy z bazy danych do macierzystego SAFEARRAY.
Przykład
W tym przykładzie tworzony klasy DatabaseClass do interakcji z ADO.NET DataTable obiektu.Należy zauważyć, że ta klasa jest macierzystym C++ class (w porównaniu z ref class lub value class).Jest to konieczne, ponieważ chcemy użyć tej klasy z kodu macierzystego i typów zarządzanych nie można używać w kodzie macierzystym.Tej klasy będą kompilowane docelowych CLR, wskazywane przez #pragma managed dyrektywy poprzedzających deklaracji klasy.Aby uzyskać więcej informacji na temat niniejszej dyrektywy, zobacz managed, unmanaged.
Uwaga prywatnego członek klasy DatabaseClass: gcroot<DataTable ^> table.Ponieważ macierzystym typów nie może zawierać typy zarządzane gcroot konieczne jest słowo kluczowe.Aby uzyskać więcej informacji na gcroot, zobacz Jak: zadeklarować uchwytów macierzystych typów.
Reszta kodu w tym przykładzie jest kodu C++ macierzystego wskazywane przez #pragma unmanaged dyrektywa poprzedzających main.W tym przykładzie jesteśmy nowe wystąpienie DatabaseClass i wywołanie jej metod tworzenia tabeli i wypełniać niektóre wiersze w tabeli.Należy zauważyć, że macierzystego SAFEARRAY typy są są przekazywane jako wartości dla kolumny bazy danych ArrayIntsCol.Wewnątrz DatabaseClass te SAFEARRAY typy są przekazywane międzyprocesowo do obiektów zarządzanych za pomocą funkcji kierującego, znajdujących się w System.Runtime.InteropServices obszaru nazw.W szczególności metody Copy jest używana do zorganizowania SAFEARRAY do tablicy liczb całkowitych i metody Copy jest używana do zorganizowania tablicy liczb całkowitych, aby SAFEARRAY.
// 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;
}
Kompilowanie kodu
Aby skompilować kod z wiersza polecenia, Zapisz przykładowy kod w pliku o nazwie adonet_marshal_safearray.cpp, a następnie wprowadź następującą instrukcję:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_safearray.cpp
Zabezpieczenia
Aby uzyskać informacje dotyczące kwestii bezpieczeństwa, obejmujące ADO.NET, see Securing ADO.NET Applications.
Zobacz też
Informacje
System.Runtime.InteropServices