13

I have following C# code in a console application.

Whenever I debug the application and run the query1 (which inserts a new value into the database) and then run query2 (which displays all the entries in the database), I can see the new entry I inserted clearly. However, when I close the application and check the table in the database (in Visual Studio), it is gone. I have no idea why it is not saving.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlServerCe;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string fileName = "FlowerShop.sdf";
                string fileLocation = "|DataDirectory|\\";
                DatabaseAccess dbAccess = new DatabaseAccess();
                dbAccess.Connect(fileName, fileLocation);

                Console.WriteLine("Connected to the following database:\n"+fileLocation + fileName+"\n");
                string query = "Insert into Products(Name, UnitPrice, UnitsInStock) values('NewItem', 500, 90)";
                string res = dbAccess.ExecuteQuery(query);
                Console.WriteLine(res);

                string query2 = "Select * from Products";
                string res2 = dbAccess.QueryData(query2);
                Console.WriteLine(res2);
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Console.ReadLine();
            }
        }
    }

    class DatabaseAccess
    {
        private SqlCeConnection _connection;

        public void Connect(string fileName, string fileLocation)
        {
            Connect(@"Data Source=" + fileLocation + fileName);
        }

        public void Connect(string connectionString)
        {
            _connection = new SqlCeConnection(connectionString);
        }

        public string QueryData(string query)
        {
            _connection.Open();
            using (SqlCeDataAdapter da = new SqlCeDataAdapter(query, _connection))
            using (DataSet ds = new DataSet("Data Set"))
            {
                da.Fill(ds);
                _connection.Close();
                return ds.Tables[0].ToReadableString(); // a extension method I created
            }
        }

        public string ExecuteQuery(string query)
        {
            _connection.Open();
            using (SqlCeCommand c = new SqlCeCommand(query, _connection))
            {
                int r = c.ExecuteNonQuery();
                _connection.Close();
                return r.ToString();
            }
        } 
    }

EDIT: Forgot to mention that I am using SQL Server Compact Edition 4 and VS2012 Express.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Joe Slater
  • 2,483
  • 6
  • 32
  • 49

2 Answers2

31

It is a quite common problem. You use the |DataDirectory| substitution string. This means that, while debugging your app in the Visual Studio environment, the database used by your application is located in the subfolder BIN\DEBUG folder (or x86 variant) of your project. And this works well as you don't have any kind of error connecting to the database and making update operations.

But then, you exit the debug session and you look at your database through the Visual Studio Server Explorer (or any other suitable tool). This window has a different connection string (probably pointing to the copy of your database in the project folder). You search your tables and you don't see the changes.

Then the problem get worse. You restart VS to go hunting for the bug in your app, but you have your database file listed between your project files and the property Copy to Output directory is set to Copy Always. At this point Visual Studio obliges and copies the original database file from the project folder to the output folder (BIN\DEBUG) and thus your previous changes are lost.

Now, your application inserts/updates again the target table, you again can't find any error in your code and restart the loop again until you decide to post or search on StackOverflow.

You could stop this problem by clicking on the database file listed in your Solution Explorer and changing the property Copy To Output Directory to Copy If Newer or Never Copy. Also you could update your connectionstring in the Server Explorer to look at the working copy of your database or create a second connection. The first one still points to the database in the project folder while the second one points to the database in the BIN\DEBUG folder. In this way you could keep the original database ready for deployment purposes and schema changes, while, with the second connection you could look at the effective results of your coding efforts.

EDIT Special warning for MS-Access database users. The simple act of looking at your table changes the modified date of your database ALSO if you don't write or change anything. So the flag Copy if Newer kicks in and the database file is copied to the output directory. With Access better use Copy Never.

Steve
  • 213,761
  • 22
  • 232
  • 286
  • Hey Steve, How can I have functionality like OP's error? I want to make changes only to the database in the bin folder after I have first 'build' the project and I want the original .mdf file in the project to stay intact. is that achievable? – Zeeshan Adil Oct 12 '19 at 04:02
  • @ZeeshanAdil I suggest you to post a new question eventually linking this answer to give context. You get more people to look at your question in this way – Steve Oct 12 '19 at 11:57
  • I posted a question linking it to your answer, in case you will be interested in having a look you can fid it here: https://stackoverflow.com/questions/58350817/how-to-save-changes-only-the-database-in-bin-folder-while-keeping-the-project-fi – Zeeshan Adil Oct 12 '19 at 13:08
  • Steve's solution helped me as well with VS 19 version Version 16.11.6. The start of the original problem with not having updates take effect originates with copying the database to the project. The user should select "No" for the "The connection you selected uses a local data file that is not in the current project. Would you like to copy the file to your project and modify the connection?" dialog box. This will make sure the application connects to the database in the external location, not the bin/debug folder. – jlakes85 Nov 13 '21 at 20:58
3

Committing changes / saving changes across debug sessions is a familiar topic in SQL CE forums. It is something that trips up quite a few people. I'll post links to source articles below, but I wanted to paste the answer that seems to get the best results to the most people:


You have several options to change this behavior. If your sdf file is part of the content of your project, this will affect how data is persisted. Remember that when you debug, all output of your project (including the sdf) if in the bin/debug folder.

  • You can decide not to include the sdf file as part of your project and manage the file location runtime.

  • If you are using "copy if newer", and project changes you make to the database will overwrite any runtime/debug changes.

  • If you are using "Do not copy", you will have to specify the location in code (as two levels above where your program is running).

  • If you have "Copy always", any changes made during runtime will always be overwritten


Answer Source

Here is a link to some further discussion and how to documentation.

Ray K
  • 1,452
  • 10
  • 17