When executing asynchronous trigger, forget the await statement and forget to use ADO Net to write to the database. Is it safe in c#?
In ASP Net application, I want to log in to the database as efficiently as possible I use basic ADO Net writes to the log database. I want to do this asynchronously, so this is what I do:
using (var conn = new sqlConnection(_connectionString)) { using (var cmd = new sqlCommand("INSERT INTO dbo.Logs (TimeStamp,ThreadId,Level,Message,Exception) VALUES (@TimeStamp,@ThreadId,@Level,@Message,@Exception)",conn)) { cmd.Parameters.AddWithValue("@TimeStamp",DateTime.UtcNow); cmd.Parameters.AddWithValue("@ThreadId",Thread.CurrentThread.ManagedThreadId); cmd.Parameters.AddWithValue("@Level",level); cmd.Parameters.AddWithValue("@Message",msg); cmd.Parameters.AddWithValue("@Exception",ex == null ? "" : ex.ToString()); conn.open(); cmd.ExecuteNonQueryAsync(); } }
Now my question is whether I should use CMD Execute nonqueryasync() statement to wait, or if you can omit the wait, because I basically only need to do it once, send and discard
Solution
Just triggering and forgetting the asynchronous operation is not enough - it may fail due to exceptions, and in this case you almost certainly want to do something (notify the user / retry / explode) (in addition, if someone uses specific options, exceptions in the task will eventually invalidate the process)
Also: who is responsible for closing the connection?
Edit: in order to make the problem of connection closing clearer, I will rewrite the using statement with try / finally (I know it is not exactly the same IL, but it is close enough to see what the problem is) – in this case, the code roughly changes to:
sqlConnection conn; try { conn = new sqlConnection("connString"); sqlCommand cmd; try { cmd = new sqlCommand("INSERT INTO dbo.Logs (TimeStamp,conn); cmd.AddParameters(); conn.open(); cmd.ExecuteNonQueryAsync(); } finally { if (cmd != null) cmd.Dispose(); } finally { if (conn != null) conn.Close(); }
You can see in CMD CMD. Is called immediately after executenonqueryasync() Dispose(). How does this work? I see two possibilities:
> cmd. Dispose() (by design or by accident) until CMD Executenonqueryasync will not return until it can complete its work - which means that you can actually only return in CMD From CMD. After executenonqueryasync Dispose returns; In this case, the code works, but you won't benefit from await / async; > Or to prevent CMD Execute CMD as executenonqueryasync() completes Dispose(); In this case, the code does not work;
In both cases, the program is wrong – you need to wait or call wait () on the task to ensure that it behaves correctly