You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello, author: I am a developer from China. My English is not very good, so my question is translated using translation software, so the meaning may not be very accurate.
When I used asynchronous query, I found a small problem. The source code is as follows
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
{
object param = command.Parameters;
var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType());
var info = GetCacheInfo(identity, param, command.AddToCache);
bool wasClosed = cnn.State == ConnectionState.Closed;
var cancel = command.CancellationToken;
using var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader);
if (cancel.CanBeCanceled)
{
cancel.Register((obj) => ((DbCommand)obj)?.Cancel(), cmd);
}
DbDataReader reader = null;
try
{
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
reader = await ExecuteReaderWithFlagsFallbackAsync(cmd, wasClosed, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, cancel).ConfigureAwait(false);
var tuple = info.Deserializer;
int hash = GetColumnHash(reader);
if (tuple.Func == null || tuple.Hash != hash)
{
if (reader.FieldCount == 0)
return Enumerable.Empty<T>();
tuple = info.Deserializer = new DeserializerState(hash, GetDeserializer(effectiveType, reader, 0, -1, false));
if (command.AddToCache) SetQueryCache(identity, info);
}
var func = tuple.Func;
if (command.Buffered)
{
var buffer = new List<T>();
var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
while (await reader.ReadAsync(cancel).ConfigureAwait(false))
{
object val = func(reader);
buffer.Add(GetValue<T>(reader, effectiveType, val));
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { /* ignore subsequent result sets */ }
command.OnCompleted();
return buffer;
}
else
{
// can't use ReadAsync / cancellation; but this will have to do
wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
var deferred = ExecuteReaderSync<T>(reader, func, command.Parameters);
reader = null; // to prevent it being disposed before the caller gets to see it
return deferred;
}
}
finally
{
using (reader) { /* dispose if non-null */ }
if (wasClosed)
cnn.Close();
}
}
When I execute a time-consuming SQL statement, if the request is canceled, that is, the value of CancellationToken.IsCancellationRequested becomes true, then the try will be jumped out and the finally block will be executed. When the reader.dispose under finally is executed, the execution will be blocked until The SQL statement is completely executed before it will continue to execute. What I think is that the request to cancel finally will not block.
Then I checked the source code from the Internet and found a solution:
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
{
object param = command.Parameters;
var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType());
var info = GetCacheInfo(identity, param, command.AddToCache);
bool wasClosed = cnn.State == ConnectionState.Closed;
var cancel = command.CancellationToken;
using var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader);
if (cancel.CanBeCanceled)
{
cancel.Register((obj) => ((DbCommand)obj)?.Cancel(), cmd);
}
DbDataReader reader = null;
try
{
if (wasClosed) await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
reader = await ExecuteReaderWithFlagsFallbackAsync(cmd, wasClosed, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, cancel).ConfigureAwait(false);
var tuple = info.Deserializer;
int hash = GetColumnHash(reader);
if (tuple.Func == null || tuple.Hash != hash)
{
if (reader.FieldCount == 0)
return Enumerable.Empty<T>();
tuple = info.Deserializer = new DeserializerState(hash, GetDeserializer(effectiveType, reader, 0, -1, false));
if (command.AddToCache) SetQueryCache(identity, info);
}
After adding cancel.Register((obj) => ((DbCommand)obj)?.Cancel(), cmd);, the program will execute smoothly
The text was updated successfully, but these errors were encountered:
Hello, author: I am a developer from China. My English is not very good, so my question is translated using translation software, so the meaning may not be very accurate.
When I used asynchronous query, I found a small problem. The source code is as follows
When I execute a time-consuming SQL statement, if the request is canceled, that is, the value of CancellationToken.IsCancellationRequested becomes true, then the try will be jumped out and the finally block will be executed. When the reader.dispose under finally is executed, the execution will be blocked until The SQL statement is completely executed before it will continue to execute. What I think is that the request to cancel finally will not block.
Then I checked the source code from the Internet and found a solution:
After adding cancel.Register((obj) => ((DbCommand)obj)?.Cancel(), cmd);, the program will execute smoothly
The text was updated successfully, but these errors were encountered: