1

I am trying to add train objects to a database to hold their details for persistence.

I have it working so I can add the trains to a list. But when I try to set up an INSERT statement to add the train objects details to a database. nothing is added to my database when i check it after. I don't get any errors thrown anywhere either.

Can anyone see anything wrong with my INSERT statement?

        //If the type combobox has Express selected
        if (cbxType.Text == "Express")
        {
            //Create a new train with its specific details
            Train train = trainFactory.TFactory("Express");
            //Checks for error when making train
            if (train == null)
                MessageBox.Show("Can't Create Train");
            else //Executes adding a new Express Train
            {
                //Stores the details of the textboxes/Combo boxes into the train details for each Train object
                train.Type = cbxType.Text;
                train.Departure = cbxDepartStation.Text;
                train.Destination = cbxDepartStation.Text;
                //Converts the time into DateTime format before passing to variable
                train.DepartureTime = TimeSpan.Parse(txtDepartureTime.Text);
                //Converts the date into DateTime format before passing to variable
                train.DepartureDay = DateTime.Parse(txtDepartureDay.Text);
                //If intermediate stops are selected. Throw exception
                if (chbPeterborough.IsChecked == true || chbDarlington.IsChecked == true ||
                            chbYork.IsChecked == true || chbNewcastle.IsChecked == true)
                {
                    throw new Exception();
                }
                //If first class radio button is checked, sets first class to true, else false
                if (chbFirstClass.IsChecked == true)
                {
                    train.FirstClass = true;
                }
                else
                {
                    train.FirstClass = false;
                }

                //Adds a train object to the train list with its specific details
                trains.add(train);

                //String to hold all the Intermediate stops together in one for displaying to user
                string intStops = string.Join(", ", train.IntermediateStop.Where(s => !string.IsNullOrEmpty(s)));

                //Sql sequence to connect to database and insert details of each train
                SqlConnection con = new SqlConnection(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Trains.mdf;Integrated Security=True");
                SqlCommand cmd = new SqlCommand();
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = "INSERT train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
                                  "VALUES ( @trainID , @departure, @destination, @type, @intermediate, @dep_time, @dep_date, @sleep, @first)";
                cmd.Parameters.AddWithValue("@trainID", train.TrainID);
                cmd.Parameters.AddWithValue("@departure", train.Departure);
                cmd.Parameters.AddWithValue("@destination", train.Destination);
                cmd.Parameters.AddWithValue("@type", train.Type);
                cmd.Parameters.AddWithValue("@intermediate", intStops);
                cmd.Parameters.AddWithValue("@dep_time", train.DepartureTime);
                cmd.Parameters.AddWithValue("@dep_date", train.DepartureDay);
                cmd.Parameters.AddWithValue("@sleep", train.SleeperBerth);
                cmd.Parameters.AddWithValue("@first", train.FirstClass);

                cmd.Connection = con;

                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
ESuth
  • 139
  • 1
  • 11
  • 3
    It seems that you are in this situation https://stackoverflow.com/questions/17147249/why-saving-changes-to-a-database-fails – Steve Nov 25 '18 at 08:44

2 Answers2

4

The whole AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!

If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Management Studio - I'm almost certain your data is there.

The real solution in my opinion would be to

  1. install SQL Server Express (and you've already done that anyway)
  2. install SQL Server Management Studio
  3. create your database in SSMS, give it a logical name (e.g. Trains)
  4. connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:

    Data Source=.\\SQLEXPRESS;Database=Trains;Integrated Security=True
    

    and everything else is exactly the same as before...

Also see Aaron Bertrand's excellent blog post Bad habits to kick: using AttachDbFileName for more background info.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • He is using LocalDB probably because he doesn't want to use the full installation of SqlServer Express and he wants to distribute its app to his customers without worrying about distributing also Sql Server and forcing them to go through the whole process of installing Sql Server Express – Steve Nov 25 '18 at 08:53
  • @Steve: if anyone is serious about developing with SQL Server, installing SQL Server Express is a very small step and well worth it, to avoid troubles like this all the time. And also: if he wants to distribute this, he **must** deal with installing SQL Server anyway - one way or another.... – marc_s Nov 25 '18 at 08:55
  • Well, in my experience this is not always true. Suppose you have a demo of your full app downloadable from Internet. Your anonymous customers want to test your app before buying it. You don't want to spend time installing and configuring Sql Server for them. But of course, if they like your app and decide to buy it then your are more than happy to install Sql Server Express for them. I agree with you on the flawed _AttachDbFileName_ approach – Steve Nov 25 '18 at 09:00
  • @Steve: I understand your point - but even to just **run** this program, at least SQL Server (Express) LocalDB must be present - and this is not an "embeddable" database (just a bunch of DLL's you can include in your setup) - it's an installation, too - just like SQL Server Express. So what benefit does that really give you?? – marc_s Nov 25 '18 at 09:02
  • Well, because I have never been able to properly install Sql Server Express from inside my setup and configuring all the required parameters (protocols, ports, security and so on) in a satsfying way. LocalDB instead is just an msi that I run from my setup [An old question of mine](https://stackoverflow.com/questions/9655362/localdb-deployment-on-client-pc) was answered here by a member of the LocalDB team and convinced me to use that approach for my demo – Steve Nov 25 '18 at 09:21
  • I'm confused as how to work SSMS. I am trying to connect to the server when it prompts me to by putting in my pc name as server name. And it is just giving me an error saying the server was not found or was not accessible? how do i connect to the server to create a database in there? – ESuth Nov 25 '18 at 09:33
  • 1
    @ESuth: if you've installed SQL Server **Express** with all the default settings, this creates a **named instance** of SQL Server - connect to it using `.\SQLEXPRESS` (or `(local)\SQLEXPRESS`) as server/instance name - as shown and mentioned in my answer, too ..... – marc_s Nov 25 '18 at 10:13
  • also I should probably have said this is for a university project, it's not for distribution at any point. I do just need a simple way of viewing these details without having to install sql server. I actualy have sql server enterprise 2017 which i am currently installing. But i am worried that if I try to open this project at uni, will it still be able to show me the updated table? I'm sure the university network does have some version of sql server installed. But does it need anything besides that for me to just open my visual studio project there and be able to run it how I would at home? – ESuth Nov 25 '18 at 10:28
  • I have the database created in SSMS. But I am getting a connection error when trying to connect to the database to add the values to the columns. I have used the connection(where MYPCNAME is the server name I connected to with SSMS to create the table): @"Data Source=.\MYPCNAME;Database=Train;Integrated Security=True" – ESuth Nov 25 '18 at 10:50
  • 1
    Nevermind. Got it all working now and I can see the results now when checking the database. Thank you so much. – ESuth Nov 25 '18 at 11:00
0

Try to change this code

 cmd.CommandText = "INSERT train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
                              "VALUES ( @trainID , @departure, @destination, @type, @intermediate, @dep_time, @dep_date, @sleep, @first)";

into

 cmd.CommandText = "INSERT INTO train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
                              "VALUES ( @trainID , @departure, @destination, @type, @intermediate, @dep_time, @dep_date, @sleep, @first)";

I only added INTO in your INSERT text query

klitz
  • 91
  • 1
  • 7