diff --git a/src/Dapper.AOT/CommandT.Query.cs b/src/Dapper.AOT/CommandT.Query.cs index 9b206bb4..069b28b1 100644 --- a/src/Dapper.AOT/CommandT.Query.cs +++ b/src/Dapper.AOT/CommandT.Query.cs @@ -51,7 +51,7 @@ public List QueryBuffered(TArgs args, [DapperAot] RowFactory? // consume entire results (avoid unobserved TDS error messages) while (state.Reader.NextResult()) { } - PostProcessAndRecycle(ref state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(ref state, args, state.Reader.CloseAndCapture()); return results; } finally @@ -90,7 +90,7 @@ public async Task> QueryBufferedAsync(TArgs args, [DapperAot] R // consume entire results (avoid unobserved TDS error messages) while (await state.Reader.NextResultAsync(cancellationToken)) { } - PostProcessAndRecycle(state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(state, args, await state.Reader.CloseAndCaptureAsync()); return results; } finally @@ -122,7 +122,7 @@ public async IAsyncEnumerable QueryUnbufferedAsync(TArgs args, [Dapp } // consume entire results (avoid unobserved TDS error messages) while (await state.Reader.NextResultAsync(cancellationToken)) { } - PostProcessAndRecycle(state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(state, args, await state.Reader.CloseAndCaptureAsync()); } finally { @@ -152,7 +152,7 @@ public IEnumerable QueryUnbuffered(TArgs args, [DapperAot] RowFactor } // consume entire results (avoid unobserved TDS error messages) while (state.Reader.NextResult()) { } - PostProcessAndRecycle(ref state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(ref state, args, state.Reader.CloseAndCapture()); } finally { @@ -198,7 +198,7 @@ static CommandBehavior SingleFlags(OneRowFlags flags) // consume entire results (avoid unobserved TDS error messages) while (state.Reader.NextResult()) { } - PostProcessAndRecycle(ref state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(ref state, args, state.Reader.CloseAndCapture()); return result; } finally @@ -241,7 +241,7 @@ static CommandBehavior SingleFlags(OneRowFlags flags) // consume entire results (avoid unobserved TDS error messages) while (await state.Reader.NextResultAsync(cancellationToken)) { } - PostProcessAndRecycle(state, args, state.Reader.RecordsAffected); + PostProcessAndRecycle(state, args, await state.Reader.CloseAndCaptureAsync()); return result; } finally diff --git a/src/Dapper.AOT/Internal/CommandUtils.cs b/src/Dapper.AOT/Internal/CommandUtils.cs index 820e37e7..a03a9fa1 100644 --- a/src/Dapper.AOT/Internal/CommandUtils.cs +++ b/src/Dapper.AOT/Internal/CommandUtils.cs @@ -1,4 +1,5 @@ using System; +using System.Data.Common; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; @@ -54,6 +55,33 @@ internal static bool IsCompletedSuccessfully(this Task task) #endif } + [MethodImpl(AggressiveOptions)] + internal static int CloseAndCapture(this DbDataReader? reader) + { + if (reader is null) return -1; + var count = reader.RecordsAffected; + reader.Close(); + return count; + } + + [MethodImpl(AggressiveOptions)] + internal static ValueTask CloseAndCaptureAsync(this DbDataReader? reader) + { +#if NETCOREAPP3_1_OR_GREATER + if (reader is null) return new(-1); + var count = reader.RecordsAffected; + var pending = reader.CloseAsync(); + return pending.IsCompletedSuccessfully ? new(count) : Deferred(pending, count); + static async ValueTask Deferred(Task pending, int count) + { + await pending; + return count; + } +#else + return new(CloseAndCapture(reader)); +#endif + } + [MethodImpl(MethodImplOptions.NoInlining)] private static void ThrowNull() => throw new ArgumentNullException("value"); diff --git a/src/Dapper.AOT/WrappedDbDataReader.cs b/src/Dapper.AOT/WrappedDbDataReader.cs index 7b278be0..31854dc8 100644 --- a/src/Dapper.AOT/WrappedDbDataReader.cs +++ b/src/Dapper.AOT/WrappedDbDataReader.cs @@ -49,7 +49,7 @@ public sealed override void Close() var state = this.state; // snapshot if (state is not null) { - commandFactory.PostProcessObject(new(state.Command!), args, state.Reader?.RecordsAffected ?? -1); + commandFactory.PostProcessObject(new(state.Command!), args, state.Reader.CloseAndCapture()); if (commandFactory.TryRecycle(state.Command!)) { state.Command = null; @@ -229,7 +229,7 @@ private async Task CloseAsyncImpl() var state = this.state; // snapshot if (state is not null) { - commandFactory.PostProcessObject(new(state.Command!), args, state.Reader?.RecordsAffected ?? -1); + commandFactory.PostProcessObject(new(state.Command!), args, await state.Reader.CloseAndCaptureAsync()); if (commandFactory.TryRecycle(state.Command!)) { state.Command = null;