Resolved Login form with Access db help

BLD0550

Member
Joined
Dec 29, 2023
Messages
7
Programming Experience
Beginner
Login form won't open main form, not reading data correctly for db.
Wondering if someone can look over a few lines of code to see if I'm missing something?
 
Sure. Post your code here as text in code tags. Not as a screenshot.

On the surface it sounds like you have two disjoint problems: sequencing of forms; and reading data from a database. I just tackling the form sequencing first (since you posted in the WinForms forum) unless that login form is dependent on correctly reading from the database to authenticate and authorize the user. In that case, probably present the database reading issue first, and we can move this to one of the database forums.
 
C#:
using System;
using System.Data;
using System.Windows.Forms;
using System.Text;
using System.Data.OleDb;
using System.Runtime.CompilerServices;


namespace TestApp
{
    public partial class FormLogin : Form
    {
            
        private OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\TestApp\TestApp.accdb;
                                                 Persist Security Info=False;");
        OleDbCommand cmd = new OleDbCommand();
        public FormLogin()
        {

            InitializeComponent();           
        }
        
        private void FormLogin_Load(object sender, EventArgs e)
        {

                conn.Open();
                dbConnected.Text = "Connected";
                conn.Close();
         }

        private void btnLogin_Click(object sender, EventArgs e)
        {

            conn.Open();
            string login = "SELECT User,Password FROM LoginTable WHERE User= ' " + txtUser.Text + " ' and Password= ' " + txtPassword.Text + " ' ";
            cmd = new OleDbCommand(login, conn);                       
            OleDbDataReader reader = cmd.ExecuteReader();
                        
            if (reader.Read() ==true)
            {

                new FormMain().Show();
                this.Hide();
            }

            else
            {

                MessageBox.Show("Login Failed");
                txtUser.Clear();
                txtPassword.Clear();
            }
            reader.Close();
            conn.Close();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {

            txtUser.Clear();
            txtPassword.Clear();
        }

        private void FormLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }
    }
}
 
That simply means that nothing was found in the database that matches your query.

If you change your query to just:
C#:
SELECT User, Password FROM LoginTable

does the reader.Read() return true?

If it does, then you can next try to see if anything in the database actually matches by adding some temporary code that looks something like:
C#:
bool match = false;
while (reader.Read())
{
    var user = reader["User"].ToString();
    var password = reader["Password"].ToString();
    if (user == txtUser.Text && password == txtPassword.Text))
    {
        match = true;
        break;
    }
}

and replace line 39 with if (match == true).

And then the most important thing: step through the code with a debugger instead of just running the code. Inspect the values. Perhaps the database values don't match the case of the inputs. Perhaps the database values or the user inputs have leading or trailing spaces.

Now a few asides not directly related to your problem but something you'll eventually want to fix:
1) Never take user input and put them directly into a SQL query like you are doing with line 35. You are inviting a SQL injection attack. Use parameterized queries instead. Obligatory cartoon:

1703912874530.png


2) Never store plain text passwords in a file or database. Store salted hashes of passwords. When the user enters their password, compute the salted hash of the password and then compare with what you have in your file or database.

3) C# naming conventions recommend not using Hungarian naming convention. If you are going to use it, use it everywhere to be consistent. Consistent code make it easier for people to read the code.
 
Last edited:
That simply means that nothing was found in the database that matches your query.

If you change your query to just:
C#:
SELECT User, Password FROM LoginTable

does the reader.Read() return true?

If it does, then you can next try to see if anything in the database actually matches by adding some temporary code that looks something like:
C#:
bool match = false;
while (reader.Read())
{
    var user = reader["User"].ToString();
    var password = reader["Password"].ToString();
    if (user == txtUser.Text && password == txtPassword.Text))
    {
        match = true;
        break;
    }
}

and replace line 39 with if (match == true).

And then the most important thing: step through the code with a debugger instead of just running the code. Inspect the values. Perhaps the database values don't match the case of the inputs. Perhaps the database values or the user inputs have leading or trailing spaces.

Now a few asides not directly related to your problem but something you'll eventually want to fix:
1) Never take user input and put them directly into a SQL query like you are doing with line 35. You are inviting a SQL injection attack. Use parameterized queries instead. Obligatory cartoon:

View attachment 3065

2) Never store plain text passwords in a file or database. Store salted hashes of passwords. When the user enters their password, compute the salted hash of the password and then compare with what you have in your file or database.

3) C# naming conventions recommend not using Hungarian naming convention. If you are going to use it, use it everywhere to be consistent. Consistent code make it easier for people to read the code.

I get a warning possible empty statement on line 45 and It opens FormMain when clicking Login with nothing entered in either txt boxes

C#:
using System;
using System.Data;
using System.Windows.Forms;
using System.Text;
using System.Data.OleDb;
using System.Runtime.CompilerServices;
using System.Diagnostics.Eventing.Reader;


namespace TestApp
{
    public partial class FormLogin : Form
    {
            
        private OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\TestApp\TestApp.accdb;
                                                 Persist Security Info=False;");
        OleDbCommand cmd = new OleDbCommand();
        public FormLogin()
        {

            InitializeComponent();           
        }
        
        private void FormLogin_Load(object sender, EventArgs e)
        {

                conn.Open();
                dbConnected.Text = "Connected";
                conn.Close();
         }

        private void btnLogin_Click(object sender, EventArgs e)
        {

            conn.Open();
            string login = "SELECT User,Password FROM LoginTable"; //WHERE User= ' " + txtUser.Text + " ' and Password= ' " + txtPassword.Text + " ' ";
            cmd = new OleDbCommand(login, conn);                       
            OleDbDataReader reader = cmd.ExecuteReader();
            bool match = false;
            while (reader.Read())
            {
            
                var user = reader["User"].ToString();
                var password = reader["Password"].ToString();
                if (user == txtUser.Text && password == txtPassword.Text) ;
                {

                    match = true;             
                }

                if (match == true)
                {

                    new FormMain().Show();
                    this.Hide();
                }
                else
                {

                    MessageBox.Show("Login Failed");
                    txtUser.Clear();
                    txtPassword.Clear();
                }
                


            }
            
            reader.Close();
            conn.Close();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {

            txtUser.Clear();
            txtPassword.Clear();
        }

        private void FormLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }
    }
}
 
There should not be a semicolon at the end of line 45.

I had an extra closing parenthesis at the end of line 6 of post #6. Sorry. I was typing on my phone.
 
There should not be a semicolon at the end of line 45.

Ugh (y) not sure how I missed that
Thankyou I appreciate the help

Been tasked with migrating an old VB6 app to something newer. I haven't done any coding since early 2000's and that was VB.

Adding another user in the db and I get my Login Failed message
and since there are 2 user now I have to click ok on the message box twice
 
Last edited:
Adding another user in the db and I get my Login Failed message
and since there are 2 users now I have to click ok on the message box twice add three results in having to click the message box 3 times
 
*sigh* I really meant what I said that you could do the check and then replace line 39. So your method would end up looking like:
C#:
private void btnLogin_Click(object sender, EventArgs e)
{
    conn.Open();
    string login = "SELECT User,Password FROM LoginTable"; //WHERE User= ' " + txtUser.Text + " ' and Password= ' " + txtPassword.Text + " ' ";
    cmd = new OleDbCommand(login, conn);                       

    OleDbDataReader reader = cmd.ExecuteReader();
    bool match = false;
    while (reader.Read())
    {
        var user = reader["User"].ToString();
        var password = reader["Password"].ToString();
        if (user == txtUser.Text && password == txtPassword.Text)
        {
            match = true;
            break;
        }
    }

    if (match == true)
    {
        new FormMain().Show();
        this.Hide();
    }
    else
    {
        MessageBox.Show("Login Failed");
        txtUser.Clear();
        txtPassword.Clear();
    }

    reader.Close();
    conn.Close();
}

Anyway, please take time to step through the code with a debugger. Inspect the value of user and password through each iteration of the while loop. match is obviously coming out to be false. The question is why.

Recall that "dela Cruz" != "Dela Cruz". Case matters when comparing strings for equality. Also that whitespace matters "hello world" != "hello world".
 
C#:
using System;
using System.Data;
using System.Windows.Forms;
using System.Text;
using System.Data.OleDb;
using System.Runtime.CompilerServices;
using System.Diagnostics.Eventing.Reader;


namespace TestApp
{
    public partial class FormLogin : Form
    {
            
        private OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\TestApp\TestApp.accdb;
                                                 Persist Security Info=False;");
        OleDbCommand cmd = new OleDbCommand();
        public FormLogin()
        {

            InitializeComponent();           
        }
        
        private void FormLogin_Load(object sender, EventArgs e)
        {

                conn.Open();
                dbConnected.Text = "Connected";
                conn.Close();
         }

        private void btnLogin_Click(object sender, EventArgs e)
        {

            conn.Open();
            string login = "SELECT User,Password FROM LoginTable";
            cmd = new OleDbCommand(login, conn);                       
            OleDbDataReader reader = cmd.ExecuteReader();
            bool match = false;
            while (reader.Read())
            {
            
                var user = reader["User"].ToString();
                var password = reader["Password"].ToString();
                if (user == txtUser.Text && password == txtPassword.Text)
                {

                    match = true;                   
                }

                if (match == true)
                {

                    new FormMain().Show();
                    this.Hide();
                }
                else
                {
                    
                    txtUser.Clear();
                    txtPassword.Clear();
                }

            }
            
            reader.Close();
            conn.Close();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {

            txtUser.Clear();
            txtPassword.Clear();
        }

        private void FormLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
        }
    }
}

I put a break on line 45.
As the debug info shows the two variables user = User3 and password = 1234, which is the last entry in the db. Everything is case matching and there are no leading or trailing spaces
 

Attachments

  • Screenshot 2024-01-02 183118.png
    Screenshot 2024-01-02 183118.png
    23.3 KB · Views: 10
  • Screenshot 2024-01-02 183808.png
    Screenshot 2024-01-02 183808.png
    8.6 KB · Views: 8
That's for one iteration of your while loop. What about the next two iterations?

Also, as aside, unless you specify a sort order in your query, there are no guarantees regard what order rows are returned to you. If you truly did set your breakpoint on line 45 and that was the first hit on the breakpoint, then as you can see you got the third row from the database as the first result.

As I mentioned above, see the other two iterations to see what values come out of the database. Visually, it looks like that the first row should match what the user entered into the textboxes, but you'll need to see what gets returned from the database because there's the possibility that there are leading or trailing spaces.
 
Last edited:
The login form should not be displaying the main form in the first place. Your Main method should display the login form and get the result back from it. If the login succeeded, the Main method creates and displays the main form. If the login failed, the Main method completes and the application exits.

I haven't read this whole thread so I apologise if I missed something relevant but either this wasn't said or it was ignored when it absolutely should not have been.
 
Line 45 should be obvious to debug during loop. Problem due to line 60+61.
 
Back
Top Bottom