Windows Forms C++/CLI <-> MySQL and umlauts

41 views Asked by At

I have the following problem: for a new project with Windows Forms C++/CLI I used my existing class for the MySQL connection with the ConnectorC++ 8.2.

However, in this project I now have the problem that both queries from the database and the insertion cause problems if there is an umlaut in the string.

I do not have this problem (with the same MySQL connection class of mine) in other projects of mine.

To clarify: I have a table with 4 columns: ID, number, number, name.

I now select the data from the table via PreparedStatements.

As long as there are no umlauts (ö ä ü) everything is fine, but as soon as an umlaut appears there are the following problems, among others:

test2   "öÄ üÜ äÄ Test irgendwas" std::string

But if I test something in the code like:

std::string test5 = "äÄ";
test5 "äÄ" std::string

it also recognizes it and displays it correctly.

This problem only occurs when I work with the database - in all other places umlauts are displayed or recognized correctly.

Does anyone have an idea what the reason could be that it causes such problems explicitly with this project?

I have already tried to set explicit to utf8 for the project itself when creating the connection:

_connection->setClientOption("character_set_client", "utf8");
_connection->setClientOption("character_set_connection", "utf8");
_connection->setClientOption("character_set_results", "utf8");

I also checked the settings of the project and changed it to "Not Set" under "Properties" -> "Configuration Properties" -> "Advance" -> "Character Set".

I also tried once to convert a std::string to std::wstring, which then displayed the umlauts correctly. Converting it back to a std::string then caused the same problems again.

#include "MainForm.h"

#include <jdbc/mysql_driver.h>
#include <jdbc/mysql_connection.h>
#include <jdbc/cppconn/prepared_statement.h>
#include <jdbc/cppconn/resultset.h>
#include <jdbc/cppconn/statement.h>

TestProject::MainForm::MainForm()
{
 InitializeComponent();
 //
 //TODO: Add the constructor code here
 //

 LoadMainWindowDataFromDatabase();
}

void TestProject::MainForm::LoadMainWindowDataFromDatabase()
{
 sql::mysql::MySQL_Driver* driver;
 driver = sql::mysql::get_mysql_driver_instance();
 sql::Connection* connection;

 try
 {
 connection = driver->connect("localhost:3306", "user", "Password");

 // Select the database
 connection->setSchema("db_47739_7");

 connection->setClientOption("character_set_client", "utf8");
 connection->setClientOption("character_set_connection", "utf8");
 connection->setClientOption("character_set_results", "utf8");
 }
 catch (sql::SQLException& e)
 {
 std::string errorMessage = "MySQL-Error: ";
 errorMessage += e.what();
 return;
 }
 catch (std::exception& e)
 {
 std::string errorMessage = "MySQL - Error: : ";
 errorMessage += e.what();
 return;
 }
 catch (...)
 {
 std::string errorMessage = "MySQL - Error: OpenMySQLConnection - Unknown exception caught.";
 return;
 }

 std::string query = "SELECT sahq.ArticleID, sahq.Quantity, ad.Manufacturer, ad.ArticleNumber, ad.ArticleName FROM storage_article_history_quantity AS sahq JOIN article_database AS ad ON sahq.ArticleID = ad.ID ORDER BY sahq.quantity DESC LIMIT 10 ";
 sql::PreparedStatement* preQuery = connection->prepareStatement(query);

 sql::ResultSet* result = preQuery->executeQuery();

 if (!result)
 return;

 sql::ResultSetMetaData* metaData = result->getMetaData();
 int numCols = metaData->getColumnCount();
 std::vector<std::vector<std::string>> data;
 data.clear();

 /*
 // int int string string string
 SELECT sahq.ArticleID, sahq.Quantity, ad.Manufacturer, ad.ArticleNumber, ad.ArticleName
 FROM storage_article_history_quantity AS sahq JOIN article_database AS ad ON sahq.ArticleID = ad.ID ORDER BY sahq.quantity DESC LIMIT 10
 */

 while (result->next())
 {
 std::vector<std::string> rowData;
 for (int col = 1; col <= numCols; ++col)
 {
 std::string cellValue;
 if (col == 1 || col == 2)
 cellValue = std::to_string(result->getInt(col));
 else
 cellValue = result->getString(col);

 if (col == 5)
 {
 std::string test2 = result->getString(5);
 sql::SQLString test4 = result->getString(5);
 std::string test5;
 test5 = "äÄ";
 }
 }
 }
}

mainForm.h

#pragma once

#include <vector>

namespace TestProject {

 using namespace System;
 using namespace System::ComponentModel;
 using namespace System::Collections;
 using namespace System::Windows::Forms;
 using namespace System::Data;
 using namespace System::Drawing;

 /// <summary>
 /// Summary for MainForm
 /// </summary>
 public ref class MainForm : public System::Windows::Forms::Form
 {
 public:
 MainForm();


 protected:
 /// <summary>
 /// Clean up any resources being used.
 /// </summary>
 ~MainForm()
 {
 if (components)
 {
 delete components;
 }
 }
 private:
 void LoadMainWindowDataFromDatabase();


 private: System::Windows::Forms::DataGridView^ dataGridView1;
 protected:
 private: System::Windows::Forms::Button^ button1;

 private:
 /// <summary>
 /// Required designer variable.
 /// </summary>
 System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
 /// <summary>
 /// Required method for Designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 void InitializeComponent(void)
 {
 this->dataGridView1 = (gcnew System::Windows::Forms::DataGridView());
 this->button1 = (gcnew System::Windows::Forms::Button());
 (cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dataGridView1))->BeginInit();
 this->SuspendLayout();
 // 
 // dataGridView1
 // 
 this->dataGridView1->ColumnHeadersHeightSizeMode = System::Windows::Forms::DataGridViewColumnHeadersHeightSizeMode::AutoSize;
 this->dataGridView1->Location = System::Drawing::Point(57, 257);
 this->dataGridView1->Name = L"dataGridView1";
 this->dataGridView1->Size = System::Drawing::Size(518, 150);
 this->dataGridView1->TabIndex = 0;
 // 
 // button1
 // 
 this->button1->Location = System::Drawing::Point(314, 71);
 this->button1->Name = L"button1";
 this->button1->Size = System::Drawing::Size(75, 23);
 this->button1->TabIndex = 1;
 this->button1->Text = L"button1";
 this->button1->UseVisualStyleBackColor = true;
 // 
 // MainForm
 // 
 this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
 this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
 this->ClientSize = System::Drawing::Size(666, 456);
 this->Controls->Add(this->button1);
 this->Controls->Add(this->dataGridView1);
 this->Name = L"MainForm";
 this->Text = L"MainForm";
 (cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->dataGridView1))->EndInit();
 this->ResumeLayout(false);

 }
#pragma endregion
 };
}

main.cpp

#pragma once

#include "MainForm.h"

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Reflection;

int main2(array<String^>^ args)
{
 Application::EnableVisualStyles();
 Application::SetCompatibleTextRenderingDefault(false);
 Application::Run(gcnew TestProject::MainForm());

 return 0;
}

I tried to make it as small as possible. Also in this version the string from the database is not correctly converted to UTF-8. It is a CLR Empty Project(.Net Framework) with .Net Framework 4.8

0

There are 0 answers