protected virtual int Fill(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) { int num; IntPtr ptr; Bid.ScopeEnter( out ptr, " <comm.DataAdapter.Fill|API> %d#, dataSet, srcTable, dataReader, startRecord, maxRecords\n " , this .ObjectID); try { if (dataSet == null ) { throw ADP.FillRequires( " dataSet " ); } if (ADP.IsEmpty(srcTable)) { throw ADP.FillRequiresSourceTableName( " srcTable " ); } if (dataReader == null ) { throw ADP.FillRequires( " dataReader " ); } if (startRecord < 0 ) { throw ADP.InvalidStartRecord( " startRecord " , startRecord); } if (maxRecords < 0 ) { throw ADP.InvalidMaxRecords( " maxRecords " , maxRecords); } if (dataReader.IsClosed) { return 0 ; } DataReaderContainer container = DataReaderContainer.Create(dataReader, this .ReturnProviderSpecificTypes); num = this .FillFromReader(dataSet, null , srcTable, container, startRecord, maxRecords, null , null ); } finally { Bid.ScopeLeave( ref ptr); } return num; } 另外一个SqlCommand 的ExecuteReader方法最终调用Run方法代码如下:
internal bool Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) { if ((TdsParserState.Broken == this .State) || ( this .State == TdsParserState.Closed)) { return true ; } bool flag = false ; Label_0016: if (stateObj._internalTimeout) { runBehavior = RunBehavior.Attention; } if ((TdsParserState.Broken == this .State) || ( this .State == TdsParserState.Closed)) { goto Label_06DF; } byte token = stateObj.ReadByte(); if ((((((token != 170 ) && (token != 0xab )) && ((token != 0xad ) && (token != 0xe3 ))) && (((token != 0xac ) && (token != 0x79 )) && ((token != 160 ) && (token != 0xa1 )))) && ((((token != 0x81 ) && (token != 0x88 )) && ((token != 0xa4 ) && (token != 0xa5 ))) && (((token != 0xa9 ) && (token != 0xd3 )) && ((token != 0xd1 ) && (token != 0xfd ))))) && ((((token != 0xfe ) && (token != 0xff )) && ((token != 0x39 ) && (token != 0xed ))) && (((token != 0xae ) && (token != 0x7c )) && ((token != 120 ) && (token != 0xed ))))) { this ._state = TdsParserState.Broken; this ._connHandler.BreakConnection(); throw SQL.ParsingError(); } int tokenLength = this .GetTokenLength(token, stateObj); switch (token) { case 0xa4 : if (dataStream == null ) { this .SkipBytes(tokenLength, stateObj); } else { dataStream.TableNames = this .ProcessTableName(tokenLength, stateObj); } goto Label_06AF; case 0xa5 : if (dataStream == null ) { this .SkipBytes(tokenLength, stateObj); } else { _SqlMetaDataSet metaData = this .ProcessColInfo(dataStream.MetaData, dataStream, stateObj); dataStream.SetMetaData(metaData, false ); dataStream.BrowseModeInfoConsumed = true ; } goto Label_06AF; case 0xa9 : this .SkipBytes(tokenLength, stateObj); goto Label_06AF; case 170 : case 0xab : { if (token == 170 ) { stateObj._errorTokenReceived = true ; } SqlError error = this .ProcessError(token, stateObj); if (RunBehavior.Clean == (RunBehavior.Clean & runBehavior)) { if (error.Class >= 20 ) { this .Errors.Add(error); } } else if ((( this ._connHandler != null ) && ( this ._connHandler.Connection != null )) && ( this ._connHandler.Connection.FireInfoMessageEventOnUserErrors && (error.Class <= 0x10 ))) { this .FireInfoMessageEvent(stateObj, error); } else if (error.Class < 11 ) { this .Warnings.Add(error); } else if (error.Class <= 0x10 ) { this .Errors.Add(error); if ((dataStream != null ) && ! dataStream.IsInitialized) { runBehavior = RunBehavior.UntilDone; } } else { this .Errors.Add(error); runBehavior = RunBehavior.UntilDone; } goto Label_06AF; } case 0xac : { SqlReturnValue rec = this .ProcessReturnValue(tokenLength, stateObj); if (cmdHandler != null ) { cmdHandler.OnReturnValue(rec); } goto Label_06AF; } case 0xad : { SqlLoginAck ack = this .ProcessLoginAck(stateObj); this ._connHandler.OnLoginAck(ack); goto Label_06AF; } case 0x88 : { if (stateObj._cleanupAltMetaDataSetArray == null ) { stateObj._cleanupAltMetaDataSetArray = new _SqlMetaDataSetCollection(); } _SqlMetaDataSet altMetaDataSet = this .ProcessAltMetaData(tokenLength, stateObj); stateObj._cleanupAltMetaDataSetArray.Add(altMetaDataSet); if (dataStream != null ) { dataStream.SetAltMetaDataSet(altMetaDataSet, 0x88 != stateObj.PeekByte()); } goto Label_06AF; } case 0x79 : { int status = stateObj.ReadInt32(); if (cmdHandler != null ) { cmdHandler.OnReturnStatus(status); } goto Label_06AF; } case 0x81 : if (tokenLength != 0xffff ) { stateObj._cleanupMetaData = this .ProcessMetaData(tokenLength, stateObj); } else if (cmdHandler != null ) { stateObj._cleanupMetaData = cmdHandler.MetaData; } if (dataStream != null ) { byte num5 = stateObj.PeekByte(); dataStream.SetMetaData(stateObj._cleanupMetaData, ( 0xa4 == num5) || ( 0xa5 == num5)); } else if (bulkCopyHandler != null ) { bulkCopyHandler.SetMetaData(stateObj._cleanupMetaData); } goto Label_06AF; case 0xd1 : if (bulkCopyHandler == null ) { if (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior)) { this .SkipRow(stateObj._cleanupMetaData, stateObj); } break ; } this .ProcessRow(stateObj._cleanupMetaData, bulkCopyHandler.CreateRowBuffer(), bulkCopyHandler.CreateIndexMap(), stateObj); break ; case 0xd3 : if (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior)) { int num8 = stateObj.ReadUInt16(); this .SkipRow(stateObj._cleanupAltMetaDataSetArray[num8], stateObj); } flag = true ; goto Label_06AF; case 0xe3 : { SqlEnvChange[] changeArray = this .ProcessEnvChange(tokenLength, stateObj); for ( int i = 0 ; i < changeArray.Length; i ++ ) { if (changeArray[i] == null ) { continue ; } switch (changeArray[i].type) { case 8 : case 11 : this ._currentTransaction = this ._pendingTransaction; this ._pendingTransaction = null ; if ( this ._currentTransaction == null ) { break ; } this ._currentTransaction.TransactionId = changeArray[i].newLongValue; goto Label_048E; case 9 : case 12 : case 0x11 : this ._retainedTransactionId = 0L ; goto Label_04D1; case 10 : goto Label_04D1; default : goto Label_0551; } TransactionType type = ( 8 == changeArray[i].type) ? TransactionType.LocalFromTSQL : TransactionType.Distributed; this ._currentTransaction = new SqlInternalTransaction( this ._connHandler, type, null , changeArray[i].newLongValue); Label_048E: if (( this ._statistics != null ) && ! this ._statisticsIsInTransaction) { this ._statistics.SafeIncrement( ref this ._statistics._transactions); } this ._statisticsIsInTransaction = true ; this ._retainedTransactionId = 0L ; continue ; Label_04D1: if ( this ._currentTransaction != null ) { if ( 9 == changeArray[i].type) { this ._currentTransaction.Completed(TransactionState.Committed); } else if ( 10 == changeArray[i].type) { if ( this ._currentTransaction.IsDistributed && this ._currentTransaction.IsActive) { this ._retainedTransactionId = changeArray[i].oldLongValue; } this ._currentTransaction.Completed(TransactionState.Aborted); } else { this ._currentTransaction.Completed(TransactionState.Unknown); } this ._currentTransaction = null ; } this ._statisticsIsInTransaction = false ; continue ; Label_0551: this ._connHandler.OnEnvChange(changeArray[i]); } goto Label_06AF; } case 0xfd : case 0xfe : case 0xff : this .ProcessDone(cmdHandler, dataStream, ref runBehavior, stateObj); if ((token == 0xfe ) && (cmdHandler != null )) { cmdHandler.OnDoneProc(); } goto Label_06AF; case 0xed : this .ProcessSSPI(tokenLength); goto Label_06AF; default : goto Label_06AF; } if ( this ._statistics != null ) { this ._statistics.WaitForDoneAfterRow = true ; } flag = true ; Label_06AF: if ((stateObj._pendingData && (RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior))) || (( ! stateObj._pendingData && stateObj._attentionSent) && ! stateObj._attentionReceived)) { goto Label_0016; } Label_06DF: if ( ! stateObj._pendingData && ( this .CurrentTransaction != null )) { this .CurrentTransaction.Activate(); } if (stateObj._attentionSent && stateObj._attentionReceived) { stateObj._attentionSent = false ; stateObj._attentionReceived = false ; if ((RunBehavior.Clean != (RunBehavior.Clean & runBehavior)) && ! stateObj._internalTimeout) { this .Errors.Add( new SqlError( 0 , 0 , 11 , this ._server, SQLMessage.OperationCancelled(), "" , 0 )); } } if (( this ._errors != null ) || ( this ._warnings != null )) { this .ThrowExceptionAndWarning(stateObj); } return flag; } 我已经使用Reflector查看了SQLDataAdapter类型的Fill方法以及SqlCommand.ExecuteReader 方法代码。确实有使用DataReader的地方。他们是真正负责处理查询并装在数据。DataReader和DataSet应该都是数据容器。做个类比的话,应该是茶壶和茶杯的关系。至于查询数据,除了取决于容器,还和具体负责查询和装载数据的类有关系。 我文章的标题,应该说是有问题的,这种比较忽略了一个数据查询和装载的过程。有不合理的地方。现在更正。
本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/321001,如需转载请自行联系原作者