I'm playing around with the Visual Studio 11 Beta.
Given this code:
namespace KC.DataAccess.Global
{
/// <summary>Global methods for SQL access</summary>
public static class SQL
{
public async static void ExecuteNonQuery(string ConnStr, string Query)
{
if (string.IsNullOrEmpty(ConnStr)) throw new ArgumentNullException("ConnStr");
if (string.IsNullOrEmpty(Query)) throw new ArgumentNullException("Query");
SqlConnection conn = new SqlConnection(ConnStr);
SqlCommand cmd = PrepSqlConnection(ref conn, Query);
Exception exc = null;
for (int i = 0; i < 3; i++)
try { await Task.Run(() => cmd.ExecuteNonQuery()); break; }
catch (Exception ex) { Thread.Sleep(50); exc = ex; }
if (exc != null) throw new ApplicationException("Command failed after maximum attempts", exc);
conn.Close();
conn.Dispose();
}
}
}
As it is an async method, the exceptions do not seem to bubble up to the calling method. I have test cases which therefore fail:
using Target = KC.DataAccess.Global.SQL;
[TestMethod]
[TestCategory("Unit")]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteNonQueryFail1()
{
Target.ExecuteNonQuery(null, "select 1");
}
The validation part of ExecuteNonQuery is clearly throwing an exception in this case, and I see it throw when I debug it.
I have changed the test method to an async and the syntax to await Task.Run(() => Target.ExecuteNonQuery()), to no avail.
Questions:
Since your method returns void
, there is no way how the exception could propagate to the calling code. If you change the return type to Task
, you can now observe the exception, but you have to do that explicitly.
I think that the best way to modify your calling code is just to call Wait()
. If the code in the Task
threw an exception, Wait()
will throw an AggregateException
that will contain the original exception.