-1

Not sure if this is written correctly but it looks correct. I am wanting to update a record if the id already exists and insert if not.

        DataSet ds = new DataSet();

        ds.ReadXml(XDocument.Load(Application.StartupPath + @"\xml1.xml").CreateReader());


        using (var conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + Application.StartupPath + "\\Database3.mdb"))
        {
            conn.Open();

            // make two commands here
            var commInsert = new OleDbCommand("Insert INTO Table1 (description, active) VALUES (@iq_question,@active);", conn);
            var commUpdate = new OleDbCommand("UPDATE Table1 SET description=@iq_question,active=@active WHERE ID=@question_id;", conn);
            // here add your parameters with no value

            //string question_id = row[0].ToString();
            //string iq_question = row[1].ToString();
            //string active = row[4].ToString();
            commInsert.Parameters.Add(new OleDbParameter("@iq_question", OleDbType.VarChar));
            commInsert.Parameters.Add(new OleDbParameter("@active", OleDbType.VarChar));

            commUpdate.Parameters.Add(new OleDbParameter("@question_id", OleDbType.AutoNumber));
            commUpdate.Parameters.Add(new OleDbParameter("@iq_question", OleDbType.Text));
            commUpdate.Parameters.Add(new OleDbParameter("@active", OleDbType.Text));

            foreach (DataTable table in ds.Tables)
            {
                foreach (DataRow row in table.Rows)
                {
                    // here only reset the values
                    commUpdate.Parameters["@question_id"].Value = row[0].ToString();
                    commUpdate.Parameters["@iq_question"].Value = row[1].ToString();
                    commUpdate.Parameters["@active"].Value = row[4].ToString();

                    int recs = commUpdate.ExecuteNonQuery();
                    if (recs < 1) // when no records updated do insert
                    {
                        commInsert.Parameters["@iq_question"].Value = row[1].ToString();
                        commInsert.Parameters["@active"].Value = row[4].ToString();

                        commInsert.ExecuteNonQuery();
                    }
                }
            }
            commInsert.Dispose();
            commUpdate.Dispose();
            conn.Close();
        }
        System.Windows.Forms.MessageBox.Show("Updated Latest Data Was Succesfull");

I either get an error on the insert saying it will create duplicate content, or it creates more rows with different data. So say I should be getting 10 rows from the xml file, the first time I run it I get the 10 rows with the correct data. If I run it again, I end up with 10 more so being 20 but the last 10 rows show different data. I don't think I am identifying the rows in the xml file correctly and I need to do some research on that part.

Bowenac
  • 493
  • 8
  • 19
  • Have you tried to execute it? – D Stanley Jul 14 '14 at 22:43
  • 3
    You can't use `IF NOT EXIST` in Access. See this: http://stackoverflow.com/questions/19573198/insert-if-no-exists-in-access You should split query. First look for the specific row. Then, (c# code) if not exists, run the insert statement – Horaciux Jul 14 '14 at 22:46
  • Why not break that command down into steps? Would be easier to manage I think. – crthompson Jul 14 '14 at 22:47

1 Answers1

0

There is no Exists for MS Access. The engine is much more primitive than Sql Server. See here: Microsoft Access SQL. I think, what you can do is:

myCommand.CommandText = "UPDATE Table1 SET description=@iq_question,active=@active WHERE ID=@currentRow";
......
int recs = myCommand.ExecuteNonQuery();

if (recs < 1) // when no records updated do insert
{
    myCommand.Parameters.Clear();
    myCommand.CommandText = "Insert INTO Table1 VALUES(@iq_question,@active)";
    .....
}

This is still 2 statements but you can save some coding by not doing Select first. Because ExecuteNonQuery will tell you if you updated anything

Another thing is that your code is a bit inefficient. You have nested loop where you can reuse same command and connection. Yuu can do this

using (var conn = new OleDbConnection(.......))
{
    conn.Open();
    // make two commands here
    var commInsert = new OleDbCommand(.....);
    var commUpdate = new OleDbCommand(.....);
    // here add your parameters with no value
    commInsert.Parameters.Add(new OleDbParameter(....));
    .......

    Foreach (....)
    {
        Foreach (....)
        {
            // here only reset the values
            commUpdate.Parameters[0].Value = ...
            ...
            int recs = commUpdate.ExecuteNonQuery();
            if (recs < 1) // when no records updated do insert
            {
                commInsert.Parameters[0].Value = iq_question;
                .....
            }
        }
    }
    commInsert.Dispose();
    commUpdate.Dispose();
}

You can also use nested using for commands. Only setting values will be more efficient to what you do right now.

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • NM I had the execute in wrong spot... Still need to iron a couple spots out, will update if this works and mark as answer. – Bowenac Jul 14 '14 at 23:38
  • Ok its kind of working, but I get an error on the insert part even though with a blank table with all the columns it inserts the correct data but I get an error "The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again." Not sure why this is happening, all I am doing is creating the Table1 and adding the description, and active columns. ID gets auto created. – Bowenac Jul 15 '14 at 00:02
  • Should the insert be before the update? It seems like if I run it again it always hits the insert and thats when it triggers that error. Just tried that and it shows the same error with the insert being first and triggers on the execute in the insert hmmm. – Bowenac Jul 15 '14 at 00:11
  • Do you have any other columns? May be there is some constraint on the column that you don't insert to? Try to list columns like `Insert INTO Table1 (description, action) VALUES(@iq_question,@active)`. Update definitely goes first. If you do insert first then, what if you already have this row? You know, you can also retrieve your identity (in this case ID) on insert http://msdn.microsoft.com/en-us/library/ks9f57t0%28v=vs.100%29.aspx – T.S. Jul 15 '14 at 03:34
  • I played with it a bit, and I think it is how I am reading an xml file, and using those values to insert into the db. I will update OP with what I am using now. Example getting data from xml string question_id = row[0].ToString(); a couple of the columns end up with the wrong data after I changed the Insert statement. – Bowenac Jul 15 '14 at 13:37
  • So, what is your issue now? Please see update. You should do more refactoring. – T.S. Jul 15 '14 at 14:38
  • Ok thank a lot, I will try the update. I was thinking about just dropping the table then re creating. This will only be used to fetch new data from an xml file on a website etc when the desktop application has an internet connection and the hidden button is clicked etc. But I will try your update. – Bowenac Jul 15 '14 at 15:29
  • Not sure what the problem is but I'm getting connection has not been initialized at the int recs... http://pastebin.com/8qe1BrSL – Bowenac Jul 15 '14 at 16:29
  • @Bowenac You need to assign your connection to command, you dont: `var commInsert = new OleDbCommand();` Use this constructor `new OleDbCommand("Update...", conn);`. You can set the command text once, in constructor – T.S. Jul 15 '14 at 17:42
  • I updated it earlier and got it working but, it didn't update, it always added new rows etc. I couldn't get it to work so I just ended up dropping the table, creating the table, and then doing the insert which is working fine. I really wanted to get it to work like this but for some reason it always imports new rows. With different data than the first time. This could be something with my xml file but I would assume the parameter value location would be the same in the foreach each time it is ran. – Bowenac Jul 15 '14 at 21:20
  • I updated the op with the way I was trying if you want to look at it again. – Bowenac Jul 15 '14 at 21:22
  • @Bowenac your Sql looks good. If you want to know for sure if problem is data, go to the table, find the specific row, remember the Id. Put the breakpoint on `commUpdate.ExecuteNonQuery();`. Manually force the values you want into parameters and execute that line. Go, find that row in table again to verify and also check value of `recs`. I can't know what data you getting from XML and if you getting it correctly – T.S. Jul 15 '14 at 21:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57361/discussion-between-bowenac-and-t-s). – Bowenac Jul 16 '14 at 02:13