Postupy: Zařazování SAFEARRAY pro technologii ADO.NET (C++/CLI)
Ukazuje, jak přidat nativní SAFEARRAY k databázi a jak přeuspořádat spravované pole z databáze na nativní SAFEARRAY.
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 obslužných rutin 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 třídy DatabaseClass a voláme její metody, abychom vytvořili tabulku a naplnili některé její řádky.Všimněte si, že nativní typy SAFEARRAY jsou předávány jako hodnoty pro sloupec databáze ArrayIntsCol.Uvnitř DatabaseClass jsou tyto SAFEARRAY 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 Copy je použita k přeuspořádání SAFEARRAY na spravované pole celých čísel a metoda Copy je použita k přeuspořádání spravovaného pole celých čísel na 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;
}
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_safearray.cpp a zadejte následující příkaz:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_safearray.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é
Referenční dokumentace
System.Runtime.InteropServices