且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

.NET深入学习笔记(1):DataSet和SqlDataReader性能差异深入剖析与测试(2)

更新时间:2022-04-18 01:17:57

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, nullnull);
    }
    
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(0011this._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,如需转载请自行联系原作者