Demonstrates how to add a native Unicode string (wchar_t *) to a database and how to marshal a
Example
In this example, the class DatabaseClass is created to interact with an ADO.NET #pragma managed
directive preceding the class declaration. For more information on this directive, see
Note the private member of the DatabaseClass class: gcroot<DataTable ^> table
. Since native types cannot contain managed types, the gcroot keyword is necessary. For more information on gcroot, see How to: Declare Handles in Native Types.
The rest of the code in this example is native C++ code, as is indicated by the #pragma unmanaged
directive preceding main
. In this example, we are creating a new instance of DatabaseClass and calling its methods to create a table and populate some rows in the table. Note that Unicode C++ strings are being passed as values for the database column StringCol. Inside DatabaseClass, these strings are marshaled to managed strings using the marshaling functionality found in the
![]() |
---|
The memory allocated by StringToHGlobalUni must be deallocated by calling either |
В | ![]() |
---|---|
// 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; } |
Output
В | |
---|---|
StringCol: This is string 1. StringCol: This is string 2. |
Compiling the Code
-
To compile the code from the command line, save the code example in a file named adonet_marshal_string_wide.cpp and enter the following statement:
В Copy Code
cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_wide.cpp
Security
For information on security issues involving ADO.NET, see
See Also
Reference
Other Resources
Data Access Using ADO.NET in C++Native and .NET Interoperability