Acceso a datos mediante ADO.NET (C++/CLI)
ADO.NET es la API de .NET Framework para el acceso a datos y proporciona energía y facilidad de uso inigualables por las anteriores soluciones de acceso a los datos. En esta sección se describen algunos de los problemas relacionados con ADO.NET que son únicos para los usuarios de Visual C++, como serializar tipos nativos.
ADO.NET se ejecuta en Common Language Runtime (CLR). Por lo tanto, cualquier aplicación que interactúe con ADO.NET también debe tener como destino CLR. Sin embargo, esto no significa que las aplicaciones nativas no puedan usar ADO.NET. En estos ejemplos se muestra cómo interactuar con una base de datos de ADO.NET desde código nativo.
Serialización de cadenas ANSI para ADO.NET
Muestra cómo agregar una cadena nativa (char *
) a una base de datos y cómo serializar System.String desde una base de datos a una cadena nativa.
Ejemplo
En este ejemplo, se crea la clase DatabaseClass para interactuar con un objeto DataTable de ADO.NET. Tenga en cuenta que esta clase es una class
de C++ nativa (en comparación con ref class
o value class
). Esto es necesario porque queremos usar esta clase desde código nativo y no se pueden usar tipos administrados en código nativo. Esta clase se compilará para dirigirse a CLR, tal como se indica en la directiva #pragma managed
anterior a la declaración de clase. Para más información sobre esta directiva, consulte managed, unmanaged.
Anote el miembro privado de la clase DatabaseClass: gcroot<DataTable ^> table
. Dado que los tipos nativos no pueden contener tipos administrados, la palabra clave gcroot
es necesaria. Para obtener más información sobre gcroot
, consulte Declaración de manipuladores en tipos nativos.
El resto del código de este ejemplo es código de C++ nativo, como indica la directiva #pragma unmanaged
que precede a main
. En este ejemplo, vamos a crear una nueva instancia de DatabaseClass y llamar a sus métodos para crear una tabla y rellenar algunas filas de la tabla. Tenga en cuenta que las cadenas nativas de C++ se pasan como valores para la columna de base de datos StringCol. Dentro de DatabaseClass, estas cadenas se serializarán en cadenas administradas mediante la funcionalidad de serialización que se encuentra en el espacio de nombres System.Runtime.InteropServices. En concreto, el método PtrToStringAnsi se usa para serializar de char *
a String, y el método StringToHGlobalAnsi se usa para serializar un objeto String a char *
.
Nota:
La memoria asignada por StringToHGlobalAnsi se debe desasignar llamando a FreeHGlobal o GlobalFree
.
// 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.
Compilar el código
Para compilar el código desde la línea de comandos, guarde el ejemplo de código en un archivo denominado adonet_marshal_string_native.cpp y escriba la siguiente instrucción:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_native.cpp
Serialización de cadenas BSTR para ADO.NET
Muestra cómo agregar una cadena COM (BSTR
) a una base de datos y cómo serializar System.String de una base de datos a BSTR
.
Ejemplo
En este ejemplo, se crea la clase DatabaseClass para interactuar con un objeto DataTable de ADO.NET. Tenga en cuenta que esta clase es una class
de C++ nativa (en comparación con ref class
o value class
). Esto es necesario porque queremos usar esta clase desde código nativo y no se pueden usar tipos administrados en código nativo. Esta clase se compilará para dirigirse a CLR, tal como se indica en la directiva #pragma managed
anterior a la declaración de clase. Para más información sobre esta directiva, consulte managed, unmanaged.
Anote el miembro privado de la clase DatabaseClass: gcroot<DataTable ^> table
. Dado que los tipos nativos no pueden contener tipos administrados, la palabra clave gcroot
es necesaria. Para obtener más información sobre gcroot
, consulte Declaración de manipuladores en tipos nativos.
El resto del código de este ejemplo es código de C++ nativo, como indica la directiva #pragma unmanaged
que precede a main
. En este ejemplo, vamos a crear una nueva instancia de DatabaseClass y llamar a sus métodos para crear una tabla y rellenar algunas filas de la tabla. Tenga en cuenta que las cadenas COM se pasan como valores para la columna de base de datos StringCol. Dentro de DatabaseClass, estas cadenas se serializarán en cadenas administradas mediante la funcionalidad de serialización que se encuentra en el espacio de nombres System.Runtime.InteropServices. En concreto, el método PtrToStringBSTR se usa para serializar de BSTR
a String, y el método StringToBSTR se usa para serializar un objeto String a BSTR
.
Nota:
La memoria asignada por StringToBSTR se debe desasignar llamando a FreeBSTR o SysFreeString
.
// 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.
Compilar el código
Para compilar el código desde la línea de comandos, guarde el ejemplo de código en un archivo denominado adonet_marshal_string_native.cpp y escriba la siguiente instrucción:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_native.cpp
Serialización de cadenas Unicode para ADO.NET
Muestra cómo agregar una cadena nativa de Unicode (wchar_t *
) a una base de datos y cómo serializar System.String desde una base de datos a una cadena nativa de Unicode.
Ejemplo
En este ejemplo, se crea la clase DatabaseClass para interactuar con un objeto DataTable de ADO.NET. Tenga en cuenta que esta clase es una class
de C++ nativa (en comparación con ref class
o value class
). Esto es necesario porque queremos usar esta clase desde código nativo y no se pueden usar tipos administrados en código nativo. Esta clase se compilará para dirigirse a CLR, tal como se indica en la directiva #pragma managed
anterior a la declaración de clase. Para más información sobre esta directiva, consulte managed, unmanaged.
Anote el miembro privado de la clase DatabaseClass: gcroot<DataTable ^> table
. Dado que los tipos nativos no pueden contener tipos administrados, la palabra clave gcroot
es necesaria. Para obtener más información sobre gcroot
, consulte Declaración de manipuladores en tipos nativos.
El resto del código de este ejemplo es código de C++ nativo, como indica la directiva #pragma unmanaged
que precede a main
. En este ejemplo, vamos a crear una nueva instancia de DatabaseClass y llamar a sus métodos para crear una tabla y rellenar algunas filas de la tabla. Tenga en cuenta que las cadenas de C++ de Unicode se pasan como valores para la columna de base de datos StringCol. Dentro de DatabaseClass, estas cadenas se serializarán en cadenas administradas mediante la funcionalidad de serialización que se encuentra en el espacio de nombres System.Runtime.InteropServices. En concreto, el método PtrToStringUni se usa para serializar de wchar_t *
a String, y el método StringToHGlobalUni se usa para serializar un objeto String a wchar_t *
.
Nota:
La memoria asignada por StringToHGlobalUni se debe desasignar llamando a FreeHGlobal o GlobalFree
.
// 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.
Compilar el código
Para compilar el código desde la línea de comandos, guarde el ejemplo de código en un archivo denominado adonet_marshal_string_wide.cpp y escriba la siguiente instrucción:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_wide.cpp
Serialización de un tipo de datos VARIANT para ADO.NET
Muestra cómo agregar un VARIANT
nativo a una base de datos y cómo serializar System.Object desde una base de datos a un VARIANT
nativo.
Ejemplo
En este ejemplo, se crea la clase DatabaseClass para interactuar con un objeto DataTable de ADO.NET. Tenga en cuenta que esta clase es una class
de C++ nativa (en comparación con ref class
o value class
). Esto es necesario porque queremos usar esta clase desde código nativo y no se pueden usar tipos administrados en código nativo. Esta clase se compilará para dirigirse a CLR, tal como se indica en la directiva #pragma managed
anterior a la declaración de clase. Para más información sobre esta directiva, consulte managed, unmanaged.
Anote el miembro privado de la clase DatabaseClass: gcroot<DataTable ^> table
. Dado que los tipos nativos no pueden contener tipos administrados, la palabra clave gcroot
es necesaria. Para obtener más información sobre gcroot
, consulte Declaración de manipuladores en tipos nativos.
El resto del código de este ejemplo es código de C++ nativo, como indica la directiva #pragma unmanaged
que precede a main
. En este ejemplo, vamos a crear una nueva instancia de DatabaseClass y llamar a sus métodos para crear una tabla y rellenar algunas filas de la tabla. Tenga en cuenta que los tipos nativos VARIANT
se pasan como valores para la columna de base de datos ObjectCol. Dentro de DatabaseClass, estos tipos VARIANT
se serializarán en objetos administrados mediante la funcionalidad de serialización que se encuentra en el espacio de nombres System.Runtime.InteropServices. En concreto, el método GetObjectForNativeVariant se usa para serializar de VARIANT
a Object, y el método GetNativeVariantForObject se usa para serializar un objeto Object a 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;
}
ObjectCol: This is a BSTR in a VARIANT.
ObjectCol: 42
Compilar el código
Para compilar el código desde la línea de comandos, guarde el ejemplo de código en un archivo denominado adonet_marshal_variant.cpp y escriba la siguiente instrucción:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_variant.cpp
Serialización de una matriz SAFEARRAY para ADO.NET
Muestra cómo agregar un SAFEARRAY
nativo a una base de datos y cómo serializar una matriz administrada desde una base de datos a un SAFEARRAY
nativo.
Ejemplo
En este ejemplo, se crea la clase DatabaseClass para interactuar con un objeto DataTable de ADO.NET. Tenga en cuenta que esta clase es una class
de C++ nativa (en comparación con ref class
o value class
). Esto es necesario porque queremos usar esta clase desde código nativo y no se pueden usar tipos administrados en código nativo. Esta clase se compilará para dirigirse a CLR, tal como se indica en la directiva #pragma managed
anterior a la declaración de clase. Para más información sobre esta directiva, consulte managed, unmanaged.
Anote el miembro privado de la clase DatabaseClass: gcroot<DataTable ^> table
. Dado que los tipos nativos no pueden contener tipos administrados, la palabra clave gcroot
es necesaria. Para obtener más información sobre gcroot
, consulte Declaración de manipuladores en tipos nativos.
El resto del código de este ejemplo es código de C++ nativo, como indica la directiva #pragma unmanaged
que precede a main
. En este ejemplo, vamos a crear una nueva instancia de DatabaseClass y llamar a sus métodos para crear una tabla y rellenar algunas filas de la tabla. Tenga en cuenta que los tipos nativos SAFEARRAY
se pasan como valores para la columna de base de datos ArrayIntsCol. Dentro de DatabaseClass, estos tipos SAFEARRAY
se serializarán en objetos administrados mediante la funcionalidad de serialización que se encuentra en el espacio de nombres System.Runtime.InteropServices. En concreto, el método Copy se usa para serializar un SAFEARRAY
en una matriz administrada de enteros, y el método Copy se usa para serializar una matriz administrada de enteros en un 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;
}
0 1 2 3 4 5 6 7 8 9
Compilar el código
Para compilar el código desde la línea de comandos, guarde el ejemplo de código en un archivo denominado adonet_marshal_safearray.cpp y escriba la siguiente instrucción:
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_safearray.cpp
Seguridad de .NET Framework
Para obtener información sobre los problemas de seguridad relacionados con ADO.NET, consulte Protección de aplicaciones ADO.NET.
Secciones relacionadas
Sección | Descripción |
---|---|
ADO.NET | Proporciona información general sobre ADO.NET, un conjunto de clases que exponen servicios de acceso a datos para el programador de .NET. |
Consulte también
Programación de .NET con C++/CLI (Visual C++)
Interoperabilidad nativa y de .NET