QODBC problem with VisualStudio 2017 & SQL Server 2017
-
Hello!
I am trying to create a LoginForm but it keeps hitting a breakpoint at
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
saying "unhandled exception ntdll.dll a heap has been corrupted".Here is my code(I am using Visual Studio 2017 with QtVS and SQL Server Express 2017 for the database) :
#include "f1_system.h" #include <QtSql/qsqldatabase.h> #include <QtSql/qsqlquery.h> #include <QtSql/qsqlerror.h> #include <QtSql/qsqldriver.h> F1_System::F1_System(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); connect(ui.loginPushButton, SIGNAL(clicked()), this, SLOT(validateLogin())); } void F1_System::validateLogin() { QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); db.setConnectOptions(); QSqlQuery qry; QString connectionString = "Driver={SQL Server};Server=DESKTOP-4K9MAS2\\SQLEXPRESS01;Database=Formula1_BD;Trusted_Connection=yes;"; db.setDatabaseName(connectionString); db.open(); if (db.isOpen()){ qry.prepare("SELECT Username FROM Users WHERE Username = '" + ui.usernameInputField->text() + "' AND Userpassword = '" + ui.passwordInputField->text() + "';"); if (qry.exec()) { if (qry.next()) ui.label->setText("Status: You are logged in!"); else ui.label->setText("Status: Wrong credentials!\nTry again!"); } else ui.label->setText(qry.lastError().text()); } else ui.label->setText("Failed to connect to the databasef!"); db.close(); }
Does anybody know a solution?
If i just skip over those breakpoints from debugger, it validates my login. So it does what it should do.
-
@Ovidiu_GCO Why do you call addDatabase inside validateLogin? You should call it once, for example in the constructor.
"but it keeps hitting a breakpoint" - I don't get it - did you set a breakpoint at that line? A break point is there to stop when running your app through the debugger. -
@jsulm Thank you for your reply.
I moved "addDatabase" in the constructor, as you suggested (also declared "db" as a field of F1_System class) and now the "unhandled exception" is hitting atdb.close()
.I didn't place any breakpoints, but it says this :
F1_System.exe has triggered a breakpoint. occurred
If i press "Continue" in the debugger, it says:
Unhandled exception at 0x00007FFEE6DA4D3B (ntdll.dll) in F1_System.exe: 0xC0000374: A heap has been corrupted (parameters: 0x00007FFEE6E097B0). occurred
Any idea on what could i do now?
Thank you for your time. -
@Ovidiu_GCO Why do you constantly open and close the db connection?
Also, there is no need for this db member. You can get the connection at any time usingQSqlDatabase db = QSqlDatabase::database();
as explained in http://doc.qt.io/qt-5/qsqldatabase.html
And what is this:qry.~QSqlQuery();
!!!
Why do you call destructor explicitly?! -
@jsulm That is a mistake. I became desperate and I started using anything that came in my mind.
I do not understand what do you mean by "Also, there is no need for this db member. You can get the connection at any time using"
QSqlDatabase db = QSqlDatabase::database();
How should i do it?
-
@Ovidiu_GCO "also declared "db" as a field of F1_System class" - this is not needed, as you can get your db at any time as I shown you:
QSqlDatabase db = QSqlDatabase::database("QODBC");
So, there is no need to declare db as a field/member of F1_System class.
Did you read the documentation? http://doc.qt.io/qt-5/qsqldatabase.html -
@jsulm I tried to read it, but I am beginner and it is not very clear for me. Honestly, i do not really understand most of it.
I've tried this:
#include "f1_system.h" #include <QtSql/qsqldatabase.h> #include <QtSql/qsqlquery.h> #include <QtSql/qsqlerror.h> #include <QtSql/qsqldriver.h> F1_System::F1_System(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QString connectionString = "Driver={SQL Server};Server=DESKTOP-4K9MAS2\\SQLEXPRESS01;Database=Formula1_BD;Trusted_Connection=yes;"; QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName(connectionString); connect(ui.loginPushButton, SIGNAL(clicked()), this, SLOT(validateLogin())); } void F1_System::validateLogin() { QSqlQuery qry; QSqlDatabase db = QSqlDatabase::database("QODBC"); db.open(); if (db.isOpen()){ qry.prepare("SELECT Username FROM Users WHERE Username = '" + ui.usernameInputField->text() + "' AND Userpassword = '" + ui.passwordInputField->text() + "';"); if (qry.exec()) { if (qry.next()) ui.label->setText("Status: You are logged in!"); else ui.label->setText("Status: Wrong credentials!\nTry again!"); } else ui.label->setText(qry.lastError().text()); } else ui.label->setText("Failed to connect to the database!"); }
But it still didn't change a thing...
-
@Ovidiu_GCO Where does it crash now?
Also, now you open the db each time F1_System::validateLogin() is called. Why don't you do it in constructor of F1_System and close it in the corresponding destructor? -
@jsulm In the last form posted, it is occurring at the last curly-bracket(the one that closes "validateLogin()").
I tried to do as you said,
db.open()
in the constructor anddb.close()
in the destructor, but without makingQSqlDatabase db
a member of theF1_System class
it says thatidentifier "db" is undefined
, both atdb.close()
, in the destructor, and atdb.isOpen()
, in the validateLogin() method.Code:
#include "f1_system.h" #include <QtSql/qsqldatabase.h> #include <QtSql/qsqlquery.h> #include <QtSql/qsqlerror.h> #include <QtSql/qsqldriver.h> F1_System::F1_System(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); QString connectionString = "Driver={SQL Server};Server=DESKTOP-4K9MAS2\\SQLEXPRESS01;Database=Formula1_BD;Trusted_Connection=yes;"; db.setDatabaseName(connectionString); db.open(); connect(ui.loginPushButton, SIGNAL(clicked()), this, SLOT(validateLogin())); } F1_System::~F1_System() { db.close(); } void F1_System::validateLogin() { QSqlQuery qry; db = QSqlDatabase::database("QODBC"); if (db.isOpen()){ qry.prepare("SELECT Username FROM Users WHERE Username = '" + ui.usernameInputField->text() + "' AND Userpassword = '" + ui.passwordInputField->text() + "';"); if (qry.exec()) { if (qry.next()) ui.label->setText("Status: You are logged in!"); else ui.label->setText("Status: Wrong credentials!\nTry again!"); } else ui.label->setText(qry.lastError().text()); } else ui.label->setText("Failed to connect to the databasef!"); }
After that, I tried to make
QSqlDatabase db
a member of the class, but the login still fails... -
@jsulm You were right. I finally understood what you meant by getting the db at any time. Thank you very much for your help!
This is my working code:
#include "f1_system.h" #include <QtSql/qsqldatabase.h> #include <QtSql/qsqlquery.h> #include <QtSql/qsqlerror.h> #include <QtSql/qsqldriver.h> F1_System::F1_System(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QSqlDatabase db = QSqlDatabase::addDatabase("QODBC", "dataB"); QString connectionString = "Driver={SQL Server};Server=DESKTOP-4K9MAS2\\SQLEXPRESS01;Database=Formula1_BD;Trusted_Connection=yes;"; db.setDatabaseName(connectionString); connect(ui.loginPushButton, SIGNAL(clicked()), this, SLOT(validateLogin())); } F1_System::~F1_System() { QSqlDatabase::database("dataB").close(); } void F1_System::validateLogin() { if (QSqlDatabase::database("dataB").open()) { QString selectUser("SELECT Username FROM Users WHERE Username = '" + ui.usernameInputField->text() + "' AND Userpassword = '" + ui.passwordInputField->text() + "';"); QSqlQuery qry(selectUser, QSqlDatabase::database("dataB")); if (qry.next()) ui.label->setText("Status: You are logged in!"); else ui.label->setText("Status: Wrong credentials!\nTry again!"); } else ui.label->setText("Failed to connect to the database!"); }