0

So I am using c# windows form with visual studio to query an access database.

When I run with debugger and stop the application from within visual studio there is no problem, however when I run WITHOUT debugger, query the database and then close using X, the process which appears under "Apps" in Task manager becomes a background process. I can have multiple instances of this process if I run the application numerous times.

I would appreciate any information on this, Thanks!

Here is the code I am using.

    private void BtnSendQuery_Click(object sender, EventArgs e)
    {
        ReadDatabase();
    }
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        var x = MessageBox.Show("Are you sure you want to exit? ", "Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        if (x == DialogResult.No)
        {
            e.Cancel = true;
        }
        else
        {
            e.Cancel = false;
        }
    }
    private void ReadDatabase()
    {

        string CONNECTION_STR = @"Provider=Microsoft.ACE.OLEDB.12.0; 
                                  Data Source = C:\\Users\\***\\Documents\\db_folder\\access_db.accdb; 
                                  Persist Security Info = False";

        string query = ""; // query string
        OleDbConnection DB_CONNECTION = null;
        

        try
        {
            DB_CONNECTION = new OleDbConnection(CONNECTION_STR);
            DB_CONNECTION.Open();
            query = TbInputQuery.Text;
            var command = new OleDbCommand(query, DB_CONNECTION);
            var str = new StringBuilder();
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    str.AppendLine(reader["ID"].ToString());
                }
                TbOutputTable.Text = str.ToString();
            }
            DB_CONNECTION.Close();

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
            if (DB_CONNECTION != null)
            {
                DB_CONNECTION.Close();
            }
        }
    }
}

1 Answers1

0

As general rule, both your connection and cmdSQL or reader should be in a using block. While your reader is in a using block, the ALL important connection object is not.

In fact, once beyond the using block for connection? You could get away not even having using blocks for the command and reader object.

And even if a trapped error, or UN-trapped error occurs? The using block WILL ALWAYS clean up the connection.

So, for command and reader - not end of world for using block.

But, for connection? yes, always do that.

Project->settings - I would use the connection builder for the connection string - not put in code.

eg this one:

enter image description here

Then use advanced, and make sure you choose ACE (for accdb) or JET (for mdb) So this:

enter image description here

So, with above setting, then we have ONE spot in the system - never typing connecting string by hand or having to place in the code (makes change of connection very hard).

Also, don't use "any cpu" force the project to x86 for using Access x32 (or if using x64, then force project to that).

So, code say like this:

private void ReadDatabase()
{
    string CONNECTION_STR = Properties.Settings.Default.AccessDB;
    string query = ""; // query string
    try
    {
        using (OleDbConnection DB_CONNECTION = new OleDbConnection(CONNECTION_STR))
        {
            using (OleDbCommand command = new OleDbCommand(query, DB_CONNECTION))
            {
                DB_CONNECTION.Open();
                var str = new StringBuilder();
                using (OleDbDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        str.AppendLine(reader["ID"].ToString());
                    }
                    TbOutputTable.Text = str.ToString();
                }

            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
    }
}

Note in above - don't really care about the catch block - as long as the using block for the connection is built - it gets cleaned up no matter what - and even if no try/catch, or if in fact you have one!! And if a error trigger - still again, note how we do NOT have to clean up, or close the connection.

Albert D. Kallal
  • 42,205
  • 3
  • 34
  • 51
  • That is certainly a nicer way to set the connection string! I just applied all the changes you have mentioned, and I am still facing the same problem. I am building the project with x64 for 64-bit ms-access (ver 2206). – Embroider8484 Aug 04 '22 at 00:02
  • ok, x64 should be ok. The connection should close up. but, this may not be related to Access. So, when you run without debug, then closing down the app/.exe should not leave a copy of it running. Not 100% clear this is a access issue then. However, perhaps you have code that uses createObject - and a instance of say access? Also, you mentioned "back ground" process. Are you launching and running some code as separate new process thread?? – Albert D. Kallal Aug 04 '22 at 00:13
  • The code I have posted in my original question is all that is happening in the program so far, which is now your updated version. The only other thing is a button_click method which calls the ReadDatabase() method, and any other designer generated code. I’m definitely not explicitly launching a thread, also, I attached the process after closing the app to VS debugger to check for active threads and there weren’t any. Each instance of the process after closing the app takes about 20% cpu, which is much more than when the app is running. – Embroider8484 Aug 04 '22 at 00:51
  • Ok, then does running the .exe from outside of vs work ok then? It's certainly possible that vs don't release objects and memory if you run as non debug. I would run and then close project. And if still issue, then exit vs. I suspect vs might be the issue and not releasing objects. So try running outside of vs – Albert D. Kallal Aug 04 '22 at 01:25
  • Unfortunately, that did not work. Built the project as debug and release, closed VS and tried both executables, experiencing the same symptoms with both executables as running without debugger. – Embroider8484 Aug 04 '22 at 01:51
  • Try form without any access stuff - does closing the form exit the applcation? Check out this: https://stackoverflow.com/questions/12977924/how-do-i-properly-exit-a-c-sharp-application#:~:text=In%20short%2C%20yes.%20The%20entire%20application%20will%20end,you%20should%20just%20remove%20that%20form%20closed%20handler. – Albert D. Kallal Aug 04 '22 at 02:13
  • The form closes perfectly fine as long as I don't click the button which calls ReadDatabase(), I removed the form closing event from my code and just let VS deal with it but still have the same problem, in fact, that is one of the things I added to try and fix it initially. Other apps that I have made that don't access any database (this is my first database connection app) close on exit fine too. – Embroider8484 Aug 04 '22 at 02:37
  • I tried many different things, initially tried removing my form closing event, and letting VS handle it naturally, no luck there. Then I tried using Application.Exit() in the else block of the form closing event and then I also tried placing it underneath Application.Run in program.cs; which both did not fix the problem. Finally, I did the previous steps again but instead with "Environment.Exit(0);" which successfully terminates the process in both cases, but I am not totally happy with this fix. (My understanding of this, is it means that I am just forcing a hard shutdown?) – Embroider8484 Aug 04 '22 at 03:06
  • Well, I am not seeing this - but I am running vs2019, and ACE x32 bits. In debug mode, it works, and even as .exe as with my posted code - it does exit just fine. Perhaps the link I gave and this:if (System.Windows.Forms.Application.MessageLoop) { // WinForms app System.Windows.Forms.Application.Exit(); – Albert D. Kallal Aug 04 '22 at 03:18
  • It also not clear - but if you using .net core, then I would revert back to .net 4.8 framework. Using JET/ACE data engine is un-manged code - and that may well be the issue. (surprised that .net core even works with un-manged code like Access which is 25+ years old now). I would test this with setting framework to .net 4.8 - see if that works. – Albert D. Kallal Aug 04 '22 at 03:21