Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Dapper/WrappedReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,24 @@ public override long GetChars(int i, long fieldoffset, char[]? buffer, int buffe
#if NET5_0_OR_GREATER
public override Task CloseAsync() => _reader.CloseAsync();

public override ValueTask DisposeAsync() => _reader.DisposeAsync();
public override async ValueTask DisposeAsync()
{
await _reader.DisposeAsync().ConfigureAwait(false);
_reader = DisposedReader.Instance;
if (_cmd is not null)
{
if (_cmd is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync().ConfigureAwait(false);
}
else
{
_cmd.Dispose();
}

_cmd = null!;
}
}

public override Task<ReadOnlyCollection<DbColumn>> GetColumnSchemaAsync(CancellationToken cancellationToken = default) => _reader.GetColumnSchemaAsync(cancellationToken);

Expand Down
67 changes: 67 additions & 0 deletions tests/Dapper.Tests/WrappedReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ public async System.Threading.Tasks.Task DbWrappedReader_DisposeAsync_DoesNotThr
var reader = new DbWrappedReader(new DummyDbCommand(), new ThrowOnCloseDbDataReader(testOutputHelper));
await reader.DisposeAsync();
}

[Fact]
public async System.Threading.Tasks.Task DbWrappedReader_DisposeAsync_DisposesCommand()
{
var command = new DisposableTrackingDbCommand();
var reader = new DbWrappedReader(command, new StubDbDataReader());
await reader.DisposeAsync();
Assert.True(command.Disposed);
}
#endif

[Fact]
Expand All @@ -40,6 +49,64 @@ public async System.Threading.Tasks.Task WrappedBasicReader_DisposeAsync_DoesNot
}
#endif

private sealed class DisposableTrackingDbCommand : DummyDbCommand
{
public bool Disposed { get; private set; }

protected override void Dispose(bool disposing)
{
if (disposing)
{
Disposed = true;
}

base.Dispose(disposing);
}
}

#if !NETFRAMEWORK
private sealed class StubDbDataReader : DbDataReader
{
protected override void Dispose(bool disposing)
{
}

public override ValueTask DisposeAsync() => default;

public override bool GetBoolean(int ordinal) => throw new NotSupportedException();
public override byte GetByte(int ordinal) => throw new NotSupportedException();
public override long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length) => throw new NotSupportedException();
public override char GetChar(int ordinal) => throw new NotSupportedException();
public override long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length) => throw new NotSupportedException();
public override string GetDataTypeName(int ordinal) => throw new NotSupportedException();
public override DateTime GetDateTime(int ordinal) => throw new NotSupportedException();
public override decimal GetDecimal(int ordinal) => throw new NotSupportedException();
public override double GetDouble(int ordinal) => throw new NotSupportedException();
public override Type GetFieldType(int ordinal) => throw new NotSupportedException();
public override float GetFloat(int ordinal) => throw new NotSupportedException();
public override Guid GetGuid(int ordinal) => throw new NotSupportedException();
public override short GetInt16(int ordinal) => throw new NotSupportedException();
public override int GetInt32(int ordinal) => throw new NotSupportedException();
public override long GetInt64(int ordinal) => throw new NotSupportedException();
public override string GetName(int ordinal) => throw new NotSupportedException();
public override int GetOrdinal(string name) => throw new NotSupportedException();
public override string GetString(int ordinal) => throw new NotSupportedException();
public override object GetValue(int ordinal) => throw new NotSupportedException();
public override int GetValues(object[] values) => throw new NotSupportedException();
public override bool IsDBNull(int ordinal) => throw new NotSupportedException();
public override int FieldCount => 0;
public override object this[int ordinal] => throw new NotSupportedException();
public override object this[string name] => throw new NotSupportedException();
public override int RecordsAffected => 0;
public override bool HasRows => false;
public override bool IsClosed => false;
public override bool NextResult() => throw new NotSupportedException();
public override bool Read() => false;
public override int Depth => 0;
public override IEnumerator GetEnumerator() => throw new NotSupportedException();
}
#endif

private class DummyDbCommand : DbCommand
{
public override void Cancel() => throw new NotSupportedException();
Expand Down