I have the following code:
var test = new FallEnvironmentalCondition[] {
new FallEnvironmentalCondition {Id=40,FallId=3,EnvironmentalConditionId=1},
new FallEnvironmentalCondition {Id=41,FallId=3,EnvironmentalConditionId=2},
new FallEnvironmentalCondition {Id=42,FallId=3,EnvironmentalConditionId=3}
};
test.ToList().ForEach(async x => await conn.UpdateAsync(x));
I am getting the
InvalidOperationException: The connection does not support MultipleActiveResultSets
I don't understand I am await
ing each update so why am I getting this error.
Note: I have no control on the connection string so I can't turn MARS on.
You need to add attribute
MultipleActiveResultSets
in connection string and set it to true to allow multiple active result sets.Read more at: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets
The problem is the ForEach method is not an asynchronous method. It will not await the Task returned by your lambda. Running that code will fire every task and not wait for completion of any of them.
General point: marking a lambda as async does not make a synchronous method you pass it into behave asynchronously.
Solution: you will need to use a foreach loop which awaits the tasks' completion.
eg: foreach (var x in xs) await f(x);
You can wrap that in a helper method if you prefer.
(I know it's an old question, but I don't think it was clearly answered)
MARS has some limitations and also a non-zero overhead. You can use the following helpers to make the updates sequential:
So your example would turn into
I usually call the second helper instead of
Task.WhenAll
, as follows:That code starts a Task for each item in the list, but does not wait for the each task to complete before starting the next one. Inside each Task it waits for the update to complete. Try
Which is equivalent to
If you're in a non-async method you will have to Wait(), not await each task. EG