1

I am trying to update some fields in the database, using ExecuteNonQuery().

When trying to update, i receive no error or warning, and it returns me one affected row count.

The thing is, that i can only for the current request, see the change. If i reload the page or go through SMSS, the changes are not shown in the database.

Hes a little code.

    string Sql = "UPDATE AccessUser SET [" + Field + "] = '" + Database.SqlEscapeInjection(Value) + "' WHERE AccessUserID = " + User.ID;
    Response.Write("<br>" + Sql + "<br>");

    IDataReader Se = Database.CreateDataReader("SELECT * FROM AccessUser WHERE AccessUserID = " + User.ID);
    while (Se.Read())
    {
        Response.Write((string)Se[Field] + "<br>");
    }

    int affectedrows = Database.ExecuteNonQuery(Sql, Database.CreateConnection());

    Response.Write("<br>NUMMER: " + affectedrows + "<br>");
    IDataReader S = Database.CreateDataReader("SELECT * FROM AccessUser WHERE AccessUserID = " + User.ID);
   while (S.Read())
   {
       Response.Write((string)S[Field] + "<br>");
   }

As you see, i first output the current value, afterwards i run the update query, and afterwards again output the value. ( Must notify you, that i usually do use bound parameters, but for the sake of debugging i threw them away and made this. )

The result is as follow: Jonas NUMMER: 1 Mikkel

When i refresh the page, or look in the database, the row hasn't changed though. What to do? :D

EDIT: The documentation for the system "Dynamicweb-CMS" states that its not transactional: http://developer.dynamicweb-cms.com/api8/Dynamicweb~Dynamicweb.Database~ExecuteNonQuery(String,IDbConnection,IDbTransaction).html And that i should just be able to do, as i actually do. Weird stuff.

EDIT 2: To please those with a "bound parameters OCD"

    using (IDbConnection connection = Database.CreateConnection())
    {
        IDbCommand command = connection.CreateCommand();
        command.CommandText = "UPDATE AccessUser SET [" + Field + "] = @ParamValue WHERE AccessUserID = @UserId";
        Database.AddStringParam(command, "@ParamValue", Value);
        Database.AddInt32Param(command, "@UserId", User.ID);

        //Execute command
        command.ExecuteNonQuery();
        connection.Close();
    }

Same result as with the other query method.

Tried this as well. Nothing happens.

   using (SqlConnection cn = new SqlConnection(SQLString))
        {
            SqlTransaction Trans;
            try
            {

                cn.Open();
                Trans = cn.BeginTransaction();
                IDbCommand command = cn.CreateCommand();
                command.Transaction = Trans;
                command.CommandText = "UPDATE AccessUser SET [" + Field + "] = @ParamValue WHERE AccessUserID = @UserId";
                Database.AddStringParam(command, "@ParamValue", Value);
                Database.AddInt32Param(command, "@UserId", User.ID);

                //Execute command
                int affectedRecords = command.ExecuteNonQuery();
                Response.Write("<br>NUMMER: " + affectedRecords + "<br>");
                Response.Write(cn.ServerVersion );
                Trans.Commit();
                cn.Close();
            }
            catch (Exception e)
            {
                Response.Write("<span style='color:red;'>" + e.Message + "</span>");
            }
        };

I ran the profiler and see the update statement. After the update statement, the following is sent

Audit Login:
-- network protocol: LPC
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

Which, in my logic, tells me that the change is committed. Now, however, afterwards, i get this (Had to cut it down, Stackoverflow did not like it)

RPC:Completed:
exec sp_executesql N'UPDATE [AccessUser] SET [AccessUserUpdatedOn] = @p1 WHERE (([AccessUserID] = @p2) AND ((@p3 = 1 AND [AccessUserParentID] IS NULL) OR ([AccessUserParentID] = @p4)) AND ((@p5 = 1 AND [AccessUserUserName] IS NULL) OR ([AccessUserUserName] = @p6)) AND ((@p7 = 1 AND [AccessUserPassword] IS NULL) OR ([AccessUserPassword] = @p8)) AND ((@p9 = 1 AND [AccessUserName] IS NULL) OR ([AccessUserName] = @p10)) AND ((@p11 = 1 AND [AccessUserDepartment] IS NULL) OR ([AccessUserDepartment] = @p12)) AND ((@p13 = 1 AND [AccessUserEmail] IS NULL) OR ([AccessUserEmail] = @p14)) AND ((@p15 = 1 AND [AccessUserPhone] IS NULL) OR ([AccessUserPhone] = @p16)) AND ((@p17 = 1 AND [AccessUserFax] IS NULL) OR ([AccessUserFax] = @p18)) AND ((@p19 = 1 AND [AccessUserGroups] IS NULL) OR ([AccessUserGroups] = @p20)) AND ((@p21 = 1 AND [AccessUserType] IS NULL) OR ([AccessUserType] = @p22)) AND ((@p23 = 1 AND [AccessUserValidFrom] IS NULL) OR ([AccessUserValidFrom] = @p24)) AND ((@p25 = 1 AND [AccessUserValidTo] IS NULL) OR ([AccessUserValidTo] = @p26)) AND ((@p27 = 1 AND 

-and updates the content back to the original again. How would i check if this is some sort of transactional rollback? Or anything else. Pardon the English.

Jonas m
  • 2,646
  • 3
  • 22
  • 43
  • 3
    Please please please use [parameterized SQL](http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html). – Albireo Feb 07 '14 at 12:52
  • Hi Albireo - As stated in the question, i do usually use bound parameters, which in this case, did not work aswell. This syntax is purely for debugging purposes. – Jonas m Feb 07 '14 at 12:57
  • Added example with bound parameters, which results in the exact same behaviour. – Jonas m Feb 07 '14 at 13:11
  • 1
    use SQL Server profiler to check if query was actually executed on target db and check for any BEGIN TRAN calls. – PashaPash Feb 07 '14 at 13:17
  • In your last example, what was the value of 'affectedRecords' when ExecuteNonQuery completed? This will help in debugging this. – Steve Feb 07 '14 at 15:10

1 Answers1

3

You're probably using transactions. When you're using transactions, you have to commit the transaction when you're done with it, otherwise it will rollback automatically - so, in your case, you do the update, no errors. Then you check using the same SQL connection, and everything looks fine. Then at some point you leave the transaction scope, and the transaction gets rolled back automatically, reverting the change in the DB.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Sounds about right. Do you have any idéa what the common "commit" call is? – Jonas m Feb 07 '14 at 12:57
  • Was a good idéa, but sadly not where the error were to be found. i have updated my question with informations from the system i'm working in. Thank you Luaan :) – Jonas m Feb 07 '14 at 13:04
  • 1
    Possibly you have a `TransactionScope()` wrapping this at a higher level? – StuartLC Feb 07 '14 at 13:29
  • 1
    @Jonasm `TransactionScope` is one good idea, and it could also be at an even higher level - you're using ASP.NET, which can have transaction scopes over whole web service methods, and possibly even the pages itself. The transactional system is actually DB independent and it even works on a lot of other things rather than just DB. There's some way to control it using attributes (`TransactionAttribute` and others) too. Try http://msdn.microsoft.com/en-us/library/3b0dwf12(v=vs.80).aspx for some reference. – Luaan Feb 07 '14 at 13:36
  • @Luaan . Thank you for the answer again. I now tried a few different things, for example isolating my sql in a new transaction and committing it, nothing happens. I am so frustrated, somethings wrong when not even the changes the pros here recommends are working... – Jonas m Feb 07 '14 at 13:54
  • 1
    @Jonasm That's very strange... Is it possible that someone else is modifying the table at the same time? Maybe there's a background worker somewhere, or a trigger or something, and it's changing the value under your hands? Try using SQL Profiler or some other tool to watch all the SQL commands that are going to the server, if you can. – Luaan Feb 07 '14 at 15:12
  • 2
    One last thing - look for an instead of update trigger. – StuartLC Feb 08 '14 at 14:45
  • Hey again. Now back at work. I will try using the profiler today, and will post my results! Thank you all so far. – Jonas m Feb 10 '14 at 06:58
  • Okay. I now ran the profiler. This is very weird (Coming from a MySql background). I see the update statement, and that it executes correctly. After the execute it runs "RPC:Completed" exec sp_executesqæ N'UPDATE on the user again with a very very long string, resetting all fields as they were before. How come? Any ideas on what to look for? – Jonas m Feb 10 '14 at 08:26
  • 1
    @Jonasm Okay, that doesn't sound like MS SQL transaction rollback (it should probably be "Rollback Tran Starting" or something like that). Instead, it really seems as if you're manually updating the row again. This could perhaps be caused by some O/RM trying to sync changes to database, or as StuartLC suggested, an update trigger (although I'm not sure that would show up in SQL profiler). There should be some connection ID in the SQL profiler rows - does it show the same value for both the updates? If yes, that *might* weakly imply that the two updates are done over the same connection. – Luaan Feb 10 '14 at 09:28
  • 1
    @Jonasm Although now that I think about it, you might have to set the proper filters in SQL profiler to see the transaction rollback messages, I'm not entirely sure it shows them in default configuration. – Luaan Feb 10 '14 at 09:36
  • Hmm. I will try and have a closer look on the profiler. Man, this is a whole new world :) – Jonas m Feb 10 '14 at 09:42
  • Hi Luaan, Updated my question with new details. – Jonas m Feb 10 '14 at 10:43
  • Also, there are no triggers on the table. – Jonas m Feb 10 '14 at 10:54
  • 1
    @Jonasm Interesting. First, let me note that the transaction isolation level "read commited" doesn't actually mean it's been commited - it's simply one of the ways transactions work (see http://technet.microsoft.com/en-us/library/ms173763.aspx). Next, the command doesn't really explain much, other than that it seems that your table is missing a primary key (which might be why the where doesn't do a simple `Id = @p1` instead of the crazy list of conditions). In any case, you have to find out who executes the update. Are you using ASP.NET membership or something like that? – Luaan Feb 10 '14 at 11:29
  • I dont think so. Ive been put on a task to customize a CMS based solution. Is there any way to see what process/script executes the command? I will set a primary key asap. and test again to see if the command changes. thank you – Jonas m Feb 10 '14 at 11:37
  • AccessUserID is primary key as supposed to. Weird stuff. – Jonas m Feb 10 '14 at 11:38
  • Even weirder is, that the update query works just fine through sql server management studio. If i do the exact same, hardcoded query through c#, it just resets the update again. What kind of witchcraft is this, – Jonas m Feb 10 '14 at 11:47
  • 1
    @Jonasm I'm still convinced the issue is somewhere inside the O/RM, however, I couldn't find any useful reference in their documentation. It would be useful if you could somehow track the origin of the query - eg. put a breakpoint inside the ExecuteNonQuery method and see if it also gets called with the second command at some point. There are a few ways to do that, for example http://stackoverflow.com/questions/2192700/how-do-set-a-breakpoint-on-a-method-within-the-net-framework This should be great if you have the symbols for the DLLs in question. If not, you may have to do some decompilation – Luaan Feb 10 '14 at 12:16
  • Hi Luaan. The problem is now resolved! I did alot of testing with the profiler as you suggested, and tried the different options the intellisense suggested with the transactional sql as you also suggested, and somehow (Without knowing how) Succeeded in getting the sql to update without rollbacks! Thank you so much for your help, you deeply deserve the points, and i hope a lot more will come your way! – Jonas m Feb 10 '14 at 14:38
  • @Jonasm I'm glad I could be of assistance. Thanks :) – Luaan Feb 10 '14 at 14:41