0

I'm having difficulty inserting a simple record to the database. I'm not getting any errors while saving it. Also, I can verify that it got inserted if I try to retrieve it while program is running. But as soon as I close the program and refresh the database, it doesn't appear in the database. I know this is a commit problem but not sure what exactly I'm missing here.

private void saveEmpBtn_Click(object sender, EventArgs e)
{
    string aSQL = "INSERT INTO Employee(Id, Name, Type, Email, UTAId, Dept) VALUES (@Id, @Name, @Type, @Email, @UTAId, @Dept) ";

    using (conn = new SqlConnection(connectionString))
    {
        conn.Open();

        using (var tx = conn.BeginTransaction())
        using (SqlCommand command = new SqlCommand(aSQL, conn))
        {
            command.Connection = conn;
            command.Transaction = tx;

            command.Parameters.AddWithValue("@Id",  3);
            command.Parameters.AddWithValue("@Type", empTypCmbBx.SelectedItem.ToString());
            command.Parameters.AddWithValue("@Name", nmTxtBx.Text);
            command.Parameters.AddWithValue("@UTAId", utaIdTxtBx.Text);
            command.Parameters.AddWithValue("@Email", emailTxtBx.Text);
            command.Parameters.AddWithValue("@Dept", deptTxtBx.Text);

            try
            {
                command.ExecuteNonQuery();
                tx.Commit();
                conn.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        MessageBox.Show("Employee Saved Successfully");
    }
}

Included few images of database script of the table. Schema definition and ID properties as well. Some questions: the example I followed had employee.mdf and had only one table. In my case database name is RoomAllocationSystemDatabase and table name is Employee. Do I have to include schema as dot notation to access the table in the insert statement? I tried this. When I do, it says invalid object. Not sure if I need to include database name somewhere else.

CREATE TABLE [dbo].[Employee] 
(
    [Id]       INT          NOT NULL,
    [Name]     VARCHAR (50) NULL,
    [Type]     VARCHAR (50) NULL,
    [Email]    VARCHAR (50) NOT NULL,
    [UTAId]    VARCHAR (50) NULL,
    [Dept]     VARCHAR (50) NULL,
    [Password] VARCHAR (50) NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC)
);

Connection string logic while loading the form

connectionString = ConfigurationManager.ConnectionStrings["RoomAllocationSystem.Properties.Settings.RoomAllocationSystemDatabaseConnectionString"].ConnectionString;

Connection string in app.config:

<connectionStrings>
    <add name="RoomAllocationSystem.Properties.Settings.RoomAllocationSystemDatabaseConnectionString"
         connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\RoomAllocationSystemDatabase.mdf;Integrated Security=True"
         providerName="System.Data.SqlClient" />
</connectionStrings>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Not sure why it's not committed but why are you inserting an ID? You should use a primary key. Maybe that's the problem the table has a Primary Key column (Id) and your trying to insert a record without IDENTITY_INSERT ON/Off – Jeremy Thompson Apr 24 '16 at 02:09
  • @JeremyThompson Thanks for your suggestion. Tried couple of things but no success so far. If I remove Id field and specify other fields as part of insert, I get "Id can't be Null". If I remove specific fields before Values and after values all fields except Id, I get "column name or number of supplied values does not match table definition". Not sure how to insert without specifying Id. Also, not sure if my table definition is correct. Does Id in MS Access database automatically insert primary keys with Sequence? – Saurabh Gupta Apr 24 '16 at 03:24
  • It should be `SqlCommand command = new SqlCommand(aSQL, conn, tx)` if you want to use the transaction. See https://msdn.microsoft.com/en-au/library/352y4sff(v=vs.110).aspx – potatopeelings Apr 24 '16 at 04:07
  • @potatopeelings added this but still no luck. :( – Saurabh Gupta Apr 24 '16 at 04:10
  • Can you please add more oversized, blown up, useless, and unnecessary images to your post? You're not wasting enough data or making it hard enough for those reading on mobile devices yet, not to mention how useless you're making this question for those who have visual impairments. Absolutely NONE of the images you've posted are needed here. If you're not sure why you should avoid them, try copying and pasting the DDL from your `CREATE TABLE` **image** and using it to create a copy of the table. After all, it's what you would expect **us** to do with it to try and help, right? – Ken White Apr 24 '16 at 04:17
  • @SaurabhGupta - and you removed the 1st 2 lines in your innermost `using`? – potatopeelings Apr 24 '16 at 04:18
  • @KenWhite I can remove DDL image but not sure how would I add details for primary key properties and database structure. I thought they would be relevant to the post as it's hard to figure what's wrong without knowing schema structure and primary key props on database. Any suggestions? – Saurabh Gupta Apr 24 '16 at 04:22
  • @potatopeelings not sure what you meant in your comment. If you want me to remove first two lines in inner most using and test, I tried this. But still no luck. Thanks! – Saurabh Gupta Apr 24 '16 at 04:24
  • 1
    Primary key properties are established when you create that primary key, which is via the DDL. So is the database structure. If you right-click on a table in SSMS and choose to create the scripts for it, everything is written out *as text* that can be copied and pasted here, and that *we* can copy/paste to create the same table(s). You can also do that in less time than you spent creating and uploading even *one* of the images you've posted. Images should be used only when there is no other option available to demonstrate the issue. – Ken White Apr 24 '16 at 04:25
  • @KenWhite I did't get any answer for a long time so thought of including some more details. Not sure if you can discern everything from DDL but now I removed everything else and now only have code and DDL. I'm new to C# so not sure how much is sufficient. Can you please help now? – Saurabh Gupta Apr 24 '16 at 04:33
  • You asked your question two hours ago, which is not *a long time*. If you need instant answers, hire a contractor and pay them a high enough hourly rate that they will provide you immediate assistance. Sometimes questions here take days, weeks, or even months to get answers. I'll try to help, but you've only now provided useful information, and it's late where I live. – Ken White Apr 24 '16 at 04:44
  • @KenWhite I undersand. Typically response time on c# channel has been under 5-10 mins so I was comparing with that. Once again, I apologize for any inconvenience! – Saurabh Gupta Apr 24 '16 at 04:48
  • Try to see generated query by profiler or extended events on your database. Also i think conn.Close() is unnesesary because using should close connection – Piotr Lasota Apr 24 '16 at 08:27

2 Answers2

0

This is the answer. It was posted here. It is a common scenario. You have a connection string that uses the substitution string |DataDirectory|. In a desktop application this directory is usually the same directory where your program runs. Inside Visual Studio, your program run in the BIN\DEBUG (or x86 variant) directory. Thus the Visual Studio copies your MDF file from the project directory to the BIN\DEBUG folder. You add records to this copy, not to the one in the project folder. However, the Server Explorer window has a connection specific to the Project Folder database that, of course, remains empty.

You could add another connection to the Server Explorer pointing to the folder BIN\DEBUG and check that your database has been updated or not.

To complicate the matter, there is the property Copy to the Output Directory associated with the MDF file. If this property is set to Copy Always everytime you start a new debug session with Visual Studio, the file is copied again from the project folder to the output directory (BIN\DEBUG) overwriting the copy already there with a new empty one. So the first run succeds, the second one fails. And the symptoms that you observed are a clear sign of this situation.

Simply change the property Copy to the Output directory to Copy if newer, the code works well. (Peraphs it is too early, but remember to change your query to a parameterized query. As is, you could break your code simply inserting a single quote in the txtName textbox like O'Malley, not to mention the Sql Injection hack)

Community
  • 1
  • 1
-1

Try using transaction statement inside curly braces

            using (var tx = conn.BeginTransaction())
            {
                using (SqlCommand command = new SqlCommand(aSQL, conn))
                {
                    command.Connection = conn;
                    command.Transaction = tx;
                    command.Parameters.AddWithValue("@Id", 3);

                    try
                    {
                        command.ExecuteNonQuery();
                        tx.Commit();
                        conn.Close();
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
user5256439
  • 41
  • 1
  • 5