SqlDataReader

public interface IDataReader : IDisposable, IDataRecord
{
    int Depth { get; }
    int RecordsAffected { get; }

    bool IsClosed { get; }
    void Close();


    bool Read();
    bool NextResult();

    DataTable GetSchemaTable();
}

 

public abstract class DbDataReader : MarshalByRefObject, IDataReader, IEnumerable
{
    protected DbDataReader()
        : base()
    {
    }

    abstract public bool HasRows { get; }
    abstract public bool IsClosed { get; }
    abstract public int RecordsAffected { get; }

    virtual public void Close()
    {
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Close();
        }
    }

abstract public bool Read(); public Task<bool> ReadAsync() { return ReadAsync(CancellationToken.None); }
virtual public Task<bool> ReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } else { try { return Read() ? ADP.TrueTask : ADP.FalseTask; } catch (Exception e) { return ADP.CreatedTaskWithException<bool>(e); } } }

abstract public bool NextResult();
public Task<bool> NextResultAsync() { return NextResultAsync(CancellationToken.None); }
virtual public Task<bool> NextResultAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } else { try { return NextResult() ? ADP.TrueTask : ADP.FalseTask; } catch (Exception e) { return ADP.CreatedTaskWithException<bool>(e); } } }
abstract public bool IsDBNull(int ordinal); public Task<bool> IsDBNullAsync(int ordinal) { return IsDBNullAsync(ordinal, CancellationToken.None); }
virtual public 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 ADP.CreatedTaskWithException<bool>(e); } } } }

 

public class SqlDataReader : DbDataReader, IDataReader
{
    private SqlCommand _command;
    private SqlConnection _connection;

    private CommandBehavior _commandBehavior;

    private Task _currentTask;
    private Snapshot _snapshot;
    private CancellationTokenSource _cancelAsyncOnCloseTokenSource;
    private CancellationToken _cancelAsyncOnCloseToken;


    internal SqlDataReader(SqlCommand command, CommandBehavior behavior)
    {
        SqlConnection.VerifyExecutePermission();

        _command = command;
        _commandBehavior = behavior;
        if (_command != null)
        {
            _defaultTimeoutMilliseconds = (long)command.CommandTimeout * 1000L;
            _connection = command.Connection;
            if (_connection != null)
            {
                _statistics = _connection.Statistics;
                _typeSystem = _connection.TypeSystem;
            }
        }
        _sharedState._dataReady = false;
        _metaDataConsumed = false;
        _hasRows = false;
        _browseModeInfoConsumed = false;
        _currentStream = null;
        _currentTextReader = null;
        _cancelAsyncOnCloseTokenSource = new CancellationTokenSource();
        _cancelAsyncOnCloseToken = _cancelAsyncOnCloseTokenSource.Token;
        _columnDataCharsIndex = -1;
    }

override public void Close() { SqlStatistics statistics = null; IntPtr hscp; Bid.ScopeEnter(out hscp, "<sc.SqlDataReader.Close|API> %d#", ObjectID); try { statistics = SqlStatistics.StartTimer(Statistics); TdsParserStateObject stateObj = _stateObj; _cancelAsyncOnCloseTokenSource.Cancel(); var currentTask = _currentTask; if ((currentTask != null) && (!currentTask.IsCompleted)) { try { ((IAsyncResult)currentTask).AsyncWaitHandle.WaitOne(); var networkPacketTaskSource = stateObj._networkPacketTaskSource; if (networkPacketTaskSource != null) { ((IAsyncResult)networkPacketTaskSource.Task).AsyncWaitHandle.WaitOne(); } } catch (Exception) { _connection.InnerConnection.DoomThisConnection(); _isClosed = true; if (stateObj != null) { lock (stateObj) { _stateObj = null; _command = null; _connection = null; } } throw; } } CloseActiveSequentialStreamAndTextReader(); if (stateObj != null) { lock (stateObj) { if (_stateObj != null) { if (_snapshot != null) { #if DEBUG // The stack trace for replays will differ since they weren't captured during close stateObj._permitReplayStackTraceToDiffer = true; #endif PrepareForAsyncContinuation(); } SetTimeout(_defaultTimeoutMilliseconds); stateObj._syncOverAsync = true; if (!TryCloseInternal(true /*closeReader*/ )) { throw SQL.SynchronousCallMayNotPend(); } } } } } finally { SqlStatistics.StopTimer(statistics); Bid.ScopeLeave(ref hscp); } } override public bool Read() { if (_currentTask != null) { throw SQL.PendingBeginXXXExists(); } bool more; bool result; Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); result = TryReadInternal(true, out more); if (!result) { throw SQL.SynchronousCallMayNotPend(); } return more; } override public bool NextResult() { if (_currentTask != null) { throw SQL.PendingBeginXXXExists(); } bool more; bool result; Debug.Assert(_stateObj == null || _stateObj._syncOverAsync, "Should not attempt pends in a synchronous call"); result = TryNextResult(out more); if (!result) { throw SQL.SynchronousCallMayNotPend(); } return more; } public override Task<bool> ReadAsync(CancellationToken cancellationToken) { IntPtr hscp; Bid.ScopeEnter(out hscp, "<sc.SqlDataReader.ReadAsync|API> %d#", ObjectID); try { if (IsClosed) { return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(ADP.DataReaderClosed("ReadAsync"))); } if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } if (_currentTask != null) { return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(SQL.PendingBeginXXXExists())); } bool rowTokenRead = false; bool more = false; try { if ((!_haltRead) && ((!_sharedState._dataReady) || (WillHaveEnoughData(_metaData.Length - 1)))) { #if DEBUG try { _stateObj._shouldHaveEnoughData = true; #endif if (_sharedState._dataReady) { CleanPartialReadReliable(); } if (_stateObj.IsRowTokenReady()) { bool result = TryReadInternal(true, out more); Debug.Assert(result, "Should not have run out of data"); rowTokenRead = true; if (more) { if (IsCommandBehavior(CommandBehavior.SequentialAccess)) { return ADP.TrueTask; } else if (WillHaveEnoughData(_metaData.Length - 1)) { result = TryReadColumn(_metaData.Length - 1, setTimeout: true); Debug.Assert(result, "Should not have run out of data"); return ADP.TrueTask; } } else { return ADP.FalseTask; } } #if DEBUG } finally { _stateObj._shouldHaveEnoughData = false; } #endif } } catch (Exception ex) { if (!ADP.IsCatchableExceptionType(ex)) { throw; } return ADP.CreatedTaskWithException<bool>(ex); } TaskCompletionSource<bool> source = new TaskCompletionSource<bool>(); Task original = Interlocked.CompareExchange(ref _currentTask, source.Task, null); if (original != null) { source.SetException(ADP.ExceptionWithStackTrace(SQL.PendingBeginXXXExists())); return source.Task; } if (_cancelAsyncOnCloseToken.IsCancellationRequested) { source.SetCanceled(); _currentTask = null; return source.Task; } IDisposable registration = null; if (cancellationToken.CanBeCanceled) { registration = cancellationToken.Register(_command.CancelIgnoreFailure); } PrepareAsyncInvocation(useSnapshot: true); Func<Task, Task<bool>> moreFunc = null; moreFunc = (t) => { if (t != null) { Bid.Trace("<sc.SqlDataReader.ReadAsync> attempt retry %d#\n", ObjectID); PrepareForAsyncContinuation(); } if (rowTokenRead || TryReadInternal(true, out more)) { if (!more || (_commandBehavior & CommandBehavior.SequentialAccess) == CommandBehavior.SequentialAccess) { return more ? ADP.TrueTask : ADP.FalseTask; } else { if (!rowTokenRead) { rowTokenRead = true; _snapshot = null; PrepareAsyncInvocation(useSnapshot: true); } if (TryReadColumn(_metaData.Length - 1, true)) { // completed return ADP.TrueTask; } } } return ContinueRetryable(moreFunc); }; return InvokeRetryable(moreFunc, source, registration); } finally { Bid.ScopeLeave(ref hscp); } }
public override Task<bool> NextResultAsync(CancellationToken cancellationToken) { IntPtr hscp; Bid.ScopeEnter(out hscp, "<sc.SqlDataReader.NextResultAsync|API> %d#", ObjectID); try { TaskCompletionSource<bool> source = new TaskCompletionSource<bool>(); if (IsClosed) { source.SetException(ADP.ExceptionWithStackTrace(ADP.DataReaderClosed("NextResultAsync"))); return source.Task; } IDisposable registration = null; if (cancellationToken.CanBeCanceled) { if (cancellationToken.IsCancellationRequested) { source.SetCanceled(); return source.Task; } registration = cancellationToken.Register(_command.CancelIgnoreFailure); } Task original = Interlocked.CompareExchange(ref _currentTask, source.Task, null); if (original != null) { source.SetException(ADP.ExceptionWithStackTrace(SQL.PendingBeginXXXExists())); return source.Task; } if (_cancelAsyncOnCloseToken.IsCancellationRequested) { source.SetCanceled(); _currentTask = null; return source.Task; } PrepareAsyncInvocation(useSnapshot: true); Func<Task, Task<bool>> moreFunc = null; moreFunc = (t) => { if (t != null) { Bid.Trace("<sc.SqlDataReader.NextResultAsync> attempt retry %d#\n", ObjectID); PrepareForAsyncContinuation(); } bool more; if (TryNextResult(out more)) { return more ? ADP.TrueTask : ADP.FalseTask; } return ContinueRetryable(moreFunc); }; return InvokeRetryable(moreFunc, source, registration); } finally { Bid.ScopeLeave(ref hscp); } } override public Task<bool> IsDBNullAsync(int i, CancellationToken cancellationToken) { try { CheckHeaderIsReady(columnIndex: i, methodName: "IsDBNullAsync"); } catch (Exception ex) { if (!ADP.IsCatchableExceptionType(ex)) { throw; } return ADP.CreatedTaskWithException<bool>(ex); }
if ((_sharedState._nextColumnHeaderToRead > i) && (!cancellationToken.IsCancellationRequested) && (_currentTask == null)) { var data = _data; if (data != null) { return data[i].IsNull ? ADP.TrueTask : ADP.FalseTask; } else { return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(ADP.DataReaderClosed("IsDBNullAsync"))); } } else { if (_currentTask != null) { return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending())); } if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<bool>(); } try { if (WillHaveEnoughData(i, headerOnly: true)) { #if DEBUG try { _stateObj._shouldHaveEnoughData = true; #endif ReadColumnHeader(i); return _data[i].IsNull ? ADP.TrueTask : ADP.FalseTask; #if DEBUG } finally { _stateObj._shouldHaveEnoughData = false; } #endif } } catch (Exception ex) { if (!ADP.IsCatchableExceptionType(ex)) { throw; } return ADP.CreatedTaskWithException<bool>(ex); } TaskCompletionSource<bool> source = new TaskCompletionSource<bool>(); Task original = Interlocked.CompareExchange(ref _currentTask, source.Task, null); if (original != null) { source.SetException(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending())); return source.Task; } if (_cancelAsyncOnCloseToken.IsCancellationRequested) { source.SetCanceled(); _currentTask = null; return source.Task; } IDisposable registration = null; if (cancellationToken.CanBeCanceled) { registration = cancellationToken.Register(_command.CancelIgnoreFailure); } // Setup async PrepareAsyncInvocation(useSnapshot: true); // Setup the retryable function Func<Task, Task<bool>> moreFunc = null; moreFunc = (t) => { if (t != null) { PrepareForAsyncContinuation(); } if (TryReadColumnHeader(i)) { return _data[i].IsNull ? ADP.TrueTask : ADP.FalseTask; } else { return ContinueRetryable(moreFunc); } }; // Go! return InvokeRetryable(moreFunc, source, registration); } } override public Task<T> GetFieldValueAsync<T>(int i, CancellationToken cancellationToken) { try { CheckDataIsReady(columnIndex: i, methodName: "GetFieldValueAsync");
if ((!IsCommandBehavior(CommandBehavior.SequentialAccess)) && (_sharedState._nextColumnDataToRead > i) && (!cancellationToken.IsCancellationRequested) && (_currentTask == null)) { var data = _data; var metaData = _metaData; if ((data != null) && (metaData != null)) { return Task.FromResult<T>(GetFieldValueFromSqlBufferInternal<T>(data[i], metaData[i])); } else { return ADP.CreatedTaskWithException<T>(ADP.ExceptionWithStackTrace(ADP.DataReaderClosed("GetFieldValueAsync"))); } } } catch (Exception ex) { if (!ADP.IsCatchableExceptionType(ex)) { throw; } return ADP.CreatedTaskWithException<T>(ex); } if (_currentTask != null) { return ADP.CreatedTaskWithException<T>(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending())); } if (cancellationToken.IsCancellationRequested) { return ADP.CreatedTaskWithCancellation<T>(); } try { if (WillHaveEnoughData(i)) { #if DEBUG try { _stateObj._shouldHaveEnoughData = true; #endif return Task.FromResult(GetFieldValueInternal<T>(i)); #if DEBUG } finally { _stateObj._shouldHaveEnoughData = false; } #endif } } catch (Exception ex) { if (!ADP.IsCatchableExceptionType(ex)) { throw; } return ADP.CreatedTaskWithException<T>(ex); } TaskCompletionSource<T> source = new TaskCompletionSource<T>(); Task original = Interlocked.CompareExchange(ref _currentTask, source.Task, null); if (original != null) { source.SetException(ADP.ExceptionWithStackTrace(ADP.AsyncOperationPending())); return source.Task; } if (_cancelAsyncOnCloseToken.IsCancellationRequested) { source.SetCanceled(); _currentTask = null; return source.Task; } IDisposable registration = null; if (cancellationToken.CanBeCanceled) { registration = cancellationToken.Register(_command.CancelIgnoreFailure); } PrepareAsyncInvocation(useSnapshot: true); Func<Task, Task<T>> moreFunc = null; moreFunc = (t) => { if (t != null) { PrepareForAsyncContinuation(); } if (TryReadColumn(i, setTimeout: false)) { return Task.FromResult<T>(GetFieldValueFromSqlBufferInternal<T>(_data[i], _metaData[i])); } else { return ContinueRetryable(moreFunc); } }; // Go! return InvokeRetryable(moreFunc, source, registration); } }

 

posted @ 2016-11-03 22:30  茗::流  阅读(262)  评论(0)    收藏  举报
如有雷同,纯属参考。如有侵犯你的版权,请联系我。