简体   繁体   中英

Updating a DB (SQL Server) using Ids from a dataTable in C# without For loop

its my first question on SO, also I'm kinda new in c# and SqlServer. so pretty please be nice.

I have a dataTable with 4 columns: id1, id2, id3, id4 (and several rows) also I have a SQL Server DB containing the 4 columns and additional columns, 2 of them named field1 and field2

I want to Update field1 and field2 to null in the db (without using foreach Row)

I've succeeded updating the first row using this:

public void UpdateDt(DataTable dt, string ConnectionString)
{
    Conn = null;
    DataRow row =  dt.Rows[0]   
    try
    {

        Conn = new SqlConnection(ConnectionString);
        Conn.Open();
        string sql = "update [DB].[dbo].[MyTable] set [field1] = null,"+
                "[field2] = null where [ID1] = '"+row["ID1"]+"' and [ID2] = '"+row["ID2"]+"' "+
                "and [ID3] = '"+row["ID3"]+"' and [ID4] = '"+row["ID4"]+"'";
        var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
        sqlDataAdapter.UpdateCommand.CommandText = sql;
        sqlDataAdapter.UpdateCommand.BeginExecuteNonQuery();
    }
    catch( Exception ex) log(ex);
    finally
    { 
        if (Conn != null)
        {
            Conn.Close();       
            Conn.Dispose(); 
        }
    }
}

how can I update using the entire DataTable?

please help thanks in advance

-- response to comment by Soner Gönül

I've changed the sample code according to your advice, thanks

Zohar,thanks, I've chosen the fields names in order to try and make the question more general and understandable

---edit--- I've added a code for updating the entire DataTable using ForEach (with the help of Russ (thanks Russ))

 bool UpdateDt(DataTable dt)
        {
            Conn = null;
            try
            {
                Conn = new SqlConnection(ConnectionString);
                Conn.Open();
                string sql = "update [KeywordInjectionData] " +
                                              "set " +
                                              "[field1] = null " +
                                              ",[field2] = null " +
                                              "where " + 
                                              "[Id1] = @Id1" +
                                              " and [Id2] = @Id2" +
                                              " and [Id3] = @Id3" +                                                                   
                                              " and [Id4] = @Id4;" ;


                var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
                foreach (DataRow row in dt.Rows)
                {
                    sqlDataAdapter.UpdateCommand.CommandText = sql;
                    sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id1",row["Id1"]);
                    sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id2",row["Id2"]);
                    sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id3",row["Id3"]);
                    sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id4",row["Id4"]);
                    sqlDataAdapter.UpdateCommand.ExecuteNonQuery();
                    sqlDataAdapter.UpdateCommand.Parameters.Clear();
                }
            }
            catch (Exception e1)
            {
                Utillties.LogError(e1);
                return false;
            }

            finally
            {
                if (Conn != null)
                {
                    Conn.Close();
                    Conn.Dispose();
                }
            }
            return true;
        }

but the question remains, how can I update the DB without a ForEach loop?

First off, the way you are structuring your query is extremely dangerous as it will allow SQL Injections--you should only use parameterized queries (as mentioned by Soner Gonul in the comments above).

Second you can loop through each row with a Foreach clause:

Foreach (DataRow row in dt.Rows)

In doing this, however, you should move the connection declaration and open before the Foreach so that you only open the connection once.

I'm not sure why you wouldn't want to use a loop in this instance. In general, at a pure database level, loops are considered "bad", but that's really an over simplification of the issue... (I've written many queries that are faster with a loop than without)

Let's start by removing C# from the question, and instead make it "how to update all desired rows in a table at once?" Since the new values are all the same, it's possible, provided you can create the appropriate where clause. In this case, since you're attempting to update a random set of rows based on (I assume) user input, it would need to look like the following:

UPDATE dbo.MyTable
SET field1 = null, field2 = null
WHERE (id1 = @m1_id1 AND id2 = @m1_id2 AND id3 = @m1_id3)
      OR (id1 = @m2_id1 AND id2 = @m2_id2 AND id3 = @m2_id3)
      OR (id1 = @m3_id1 AND id2 = @m3_id2 AND id3 = @m3_id3)
etc.

Which get's silly rather quick. For the sake of completeness, if instead you were referencing another table in the database, it would be possible to do the following (under most RDBMS's):

UPDATE myT
SET field1 = null, field2 = null
FROM dbo.MyTable myT
    JOIN dbo.SetsToUpdate s ON myT.id1=s.id1
                            AND myT.id2=s.id2
                            AND myT.id3=s.id3

However, you're not starting with another table, and setting one up, populating it and cleaning it up most likely requires more resources than simply multiple single row updates.

So, we're back at a loop, but one that's performed in C# which does loops quite effectively. Further, aside from performance, the only other reason to want a single update statement is data atomicity, which is handled quite nicely with transactions .

If you really do see performance issues at the database level here, the question is one of database optimization (look into indexes ). But please, don't fall into the trap of premature optimization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM