| File: System\Data\Common\DbDataReader.cs | Web Access |
| Project: src\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj (System.Data.Common) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; using System.Threading.Tasks; namespace System.Data.Common { public abstract class DbDataReader : MarshalByRefObject, IDataReader, IEnumerable, IAsyncDisposable { protected DbDataReader() : base() { } public abstract int Depth { get; } public abstract int FieldCount { get; } public abstract bool HasRows { get; } public abstract bool IsClosed { get; } public abstract int RecordsAffected { get; } public virtual int VisibleFieldCount => FieldCount; public abstract object this[int ordinal] { get; } public abstract object this[string name] { get; } public virtual void Close() { } public virtual Task CloseAsync() { try { Close(); return Task.CompletedTask; } catch (Exception e) { return Task.FromException(e); } } [EditorBrowsable(EditorBrowsableState.Never)] public void Dispose() => Dispose(true); protected virtual void Dispose(bool disposing) { if (disposing) { Close(); } } public virtual ValueTask DisposeAsync() { Dispose(); return default; } public abstract string GetDataTypeName(int ordinal); [EditorBrowsable(EditorBrowsableState.Never)] public abstract IEnumerator GetEnumerator(); [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] public abstract Type GetFieldType(int ordinal); public abstract string GetName(int ordinal); public abstract int GetOrdinal(string name); /// <summary> /// Returns a <see cref="DataTable" /> that describes the column metadata of the ><see cref="DbDataReader" />. /// /// Returns <see langword="null" /> if the executed command returned no resultset, or after /// <see cref="NextResult" /> returns <see langword="false" />. /// </summary> /// <returns>A <see cref="DataTable" /> that describes the column metadata.</returns> /// <exception cref="InvalidOperationException">The <see cref="DbDataReader" /> is closed.</exception> public virtual DataTable? GetSchemaTable() { throw new NotSupportedException(); } /// <summary> /// This is the asynchronous version of <see cref="GetSchemaTable()" />. /// Providers should override with an appropriate implementation. /// The cancellation token can optionally be honored. /// The default implementation invokes the synchronous <see cref="GetSchemaTable()" /> call and /// returns a completed task. /// The default implementation will return a cancelled task if passed an already cancelled cancellationToken. /// Exceptions thrown by <see cref="GetSchemaTable()" /> will be communicated via the returned Task /// Exception property. /// </summary> /// <param name="cancellationToken">The cancellation instruction.</param> /// <returns>A task representing the asynchronous operation.</returns> public virtual Task<DataTable?> GetSchemaTableAsync(CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled<DataTable?>(cancellationToken); } try { return Task.FromResult(GetSchemaTable()); } catch (Exception e) { return Task.FromException<DataTable?>(e); } } /// <summary> /// This is the asynchronous version of <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" />. /// Providers should override with an appropriate implementation. /// The cancellation token can optionally be honored. /// The default implementation invokes the synchronous /// <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" /> call and returns a completed task. /// The default implementation will return a cancelled task if passed an already cancelled cancellationToken. /// Exceptions thrown by <see cref="DbDataReaderExtensions.GetColumnSchema(DbDataReader)" /> will be /// communicated via the returned Task Exception property. /// </summary> /// <param name="cancellationToken">The cancellation instruction.</param> /// <returns>A task representing the asynchronous operation.</returns> public virtual Task<ReadOnlyCollection<DbColumn>> GetColumnSchemaAsync( CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled<ReadOnlyCollection<DbColumn>>(cancellationToken); } try { return Task.FromResult(this.GetColumnSchema()); } catch (Exception e) { return Task.FromException<ReadOnlyCollection<DbColumn>>(e); } } public abstract bool GetBoolean(int ordinal); public abstract byte GetByte(int ordinal); public abstract long GetBytes(int ordinal, long dataOffset, byte[]? buffer, int bufferOffset, int length); public abstract char GetChar(int ordinal); public abstract long GetChars(int ordinal, long dataOffset, char[]? buffer, int bufferOffset, int length); [EditorBrowsable(EditorBrowsableState.Never)] public DbDataReader GetData(int ordinal) => GetDbDataReader(ordinal); IDataReader IDataRecord.GetData(int ordinal) => GetDbDataReader(ordinal); protected virtual DbDataReader GetDbDataReader(int ordinal) { throw ADP.NotSupported(); } public abstract DateTime GetDateTime(int ordinal); public abstract decimal GetDecimal(int ordinal); public abstract double GetDouble(int ordinal); public abstract float GetFloat(int ordinal); public abstract Guid GetGuid(int ordinal); public abstract short GetInt16(int ordinal); public abstract int GetInt32(int ordinal); public abstract long GetInt64(int ordinal); [EditorBrowsable(EditorBrowsableState.Never)] [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] public virtual Type GetProviderSpecificFieldType(int ordinal) { // NOTE: This is virtual because not all providers may choose to support // this method, since it was added in Whidbey. return GetFieldType(ordinal); } [ EditorBrowsable(EditorBrowsableState.Never) ] public virtual object GetProviderSpecificValue(int ordinal) { // NOTE: This is virtual because not all providers may choose to support // this method, since it was added in Whidbey return GetValue(ordinal); } [ EditorBrowsable(EditorBrowsableState.Never) ] public virtual int GetProviderSpecificValues(object[] values) => GetValues(values); public abstract string GetString(int ordinal); public virtual Stream GetStream(int ordinal) { using (MemoryStream bufferStream = new MemoryStream()) { long bytesRead = 0; long bytesReadTotal = 0; byte[] buffer = new byte[4096]; do { bytesRead = GetBytes(ordinal, bytesReadTotal, buffer, 0, buffer.Length); bufferStream.Write(buffer, 0, (int)bytesRead); bytesReadTotal += bytesRead; } while (bytesRead > 0); return new MemoryStream(bufferStream.ToArray(), false); } } public virtual TextReader GetTextReader(int ordinal) { if (IsDBNull(ordinal)) { return new StringReader(string.Empty); } else { return new StringReader(GetString(ordinal)); } } public abstract object GetValue(int ordinal); public virtual T GetFieldValue<T>(int ordinal) => (T)GetValue(ordinal); public Task<T> GetFieldValueAsync<T>(int ordinal) => GetFieldValueAsync<T>(ordinal, CancellationToken.None); public virtual Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<T>(); } else { try { return Task.FromResult<T>(GetFieldValue<T>(ordinal)); } catch (Exception e) { return Task.FromException<T>(e); } } } public abstract int GetValues(object[] values); public abstract bool IsDBNull(int ordinal); public Task<bool> IsDBNullAsync(int ordinal) => IsDBNullAsync(ordinal, CancellationToken.None); public virtual Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } else { try { return IsDBNull(ordinal) ? ADP.TrueTask : ADP.FalseTask; } catch (Exception e) { return Task.FromException<bool>(e); } } } public abstract bool NextResult(); public abstract bool Read(); public Task<bool> ReadAsync() => ReadAsync(CancellationToken.None); public virtual Task<bool> ReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } else { try { return Read() ? ADP.TrueTask : ADP.FalseTask; } catch (Exception e) { return Task.FromException<bool>(e); } } } public Task<bool> NextResultAsync() => NextResultAsync(CancellationToken.None); public virtual Task<bool> NextResultAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } else { try { return NextResult() ? ADP.TrueTask : ADP.FalseTask; } catch (Exception e) { return Task.FromException<bool>(e); } } } } }