0

I'm probably missing something simple. I'm trying to create load tests that call a stored procedure asynchronously and I see the calls being made in SQL Profiler but they're not actually executing. I've reduced my code to the sample below, which will result in the command showing in Profiler as if it ran even though it didn't. If you change AsynchronousProcessing to false and ExecuteScalarAsync to ExecuteScalar it works as expected.

public static void DeleteRow()
        {
            var cs = new SqlConnectionStringBuilder();
            cs.DataSource = @"SQLDEV";
            cs.InitialCatalog = "MyDB";
            cs.IntegratedSecurity = true;
            cs.AsynchronousProcessing = true;
            string connectionString = cs.ToString();
            int rowID = 127279530;
            try 
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(String.Concat(@"exec [dbo].[DeleteRow] @RowId=", rowID.ToString()), conn);
                    cmd.CommandType = System.Data.CommandType.Text;
                    cmd.ExecuteScalarAsync();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

        }

EDIT: Here's some of my original code to show what I'm trying to do.

IEnumerable<int> list = Enumerable.Range(127279517, 14);            
_queued = new ConcurrentQueue<int>(list);   

Task task1 = Task.Run(() => ProcessQueue());
Task task2 = Task.Run(() => ProcessQueue());
Task task3 = Task.Run(() => ProcessQueue());
Task task4 = Task.Run(() => ProcessQueue());
Task task5 = Task.Run(() => ProcessQueue());

Task.WaitAll(task1, task2, task2, task3, task4, task5);

and

while (_queued.TryDequeue(out rowId))
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand(String.Concat(@"exec [dbo].[DeleteRow] @RowId=", rowId.ToString()), conn);
                    cmd.CommandType = System.Data.CommandType.Text;
                    NonBlockingConsole.WriteLine(cmd.CommandText);
                    cmd.ExecuteScalarAsync();                
                }             
            }
2
  • You don't need async. Just use the synchronous version of ExecuteScalarAsync. Commented Jun 3, 2014 at 21:16
  • I don't need it in this example but I'm trying to do load testing with multiple threads called within milliseconds of each other. And even if I don't need it I'd still like to know why it shows in Profiler but isn't actually executed. Commented Jun 3, 2014 at 21:18

1 Answer 1

3

cmd.ExecuteScalarAsync() returns a task. You should probably await it and make DeleteRow itself return a task. If you are at it use OpenAsync to go fully async.

On the other hand you probably don't need async at all. Just use the synchronous version of ExecuteScalarAsync which is ExecuteScalar.

Sign up to request clarification or add additional context in comments.

4 Comments

I edited my question to show what I've tried. Isn't WaitAll equivalent to await?
If it was why would there be a need to introduce a new keyword? Very different, research the difference and make sure you get it understood. Async is a minefield of pitfalls.; Secondly, you are not waiting/awaiting the task returned by ExecuteScalarAsync anywhere. You have introduced parallelism into your app and you code is not thread-safe.; Next mistake is that you start threads but in those threads you use the async functions. That makes no sense either because ProcessQueue would return instantly had you correctly awaited the task. No need for threads.; Mines triggered, legs gone.
The answer was to use ExecuteScalar, thank you for that as my feeble DBA mind still doesn't understand the whole thing. Can you update your answer so that people know that your comment actually solved it for me, then I'll mark it as answered?
@influent I think using synchronous APIs here is the best course of action.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.