Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Data / Microsoft / SqlServer / Server / sqlpipe.cs / 3 / sqlpipe.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //daltodov //----------------------------------------------------------------------------- namespace Microsoft.SqlServer.Server { using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.Sql; using System.Data.Common; using System.Data.SqlClient; using System.Data.SqlTypes; using System.Diagnostics; // SqlPipe // Abstraction of TDS data/message channel exposed to user. #if WINFSInternalOnly internal #else public #endif sealed class SqlPipe { SmiContext _smiContext; SmiRecordBuffer _recordBufferSent; // Last recordBuffer sent to pipe (for push model SendEnd). SqlMetaData[] _metaDataSent; // Metadata of last resultset started (for push model). Overloaded to indicate if push started or not (non-null/null) SmiEventSink_Default _eventSink; // Eventsink to use when calling SmiContext entrypoints bool _isBusy; // Is this pipe currently handling an operation? bool _hadErrorInResultSet; // true if an exception was thrown from within various bodies; used to control cleanup during SendResultsEnd internal SqlPipe( SmiContext smiContext ) { _smiContext = smiContext; _eventSink = new SmiEventSink_Default(); } // // Public methods // public void ExecuteAndSend( SqlCommand command ) { SetPipeBusy( ); try { EnsureNormalSendValid( "ExecuteAndSend" ); if ( null == command ) { throw ADP.ArgumentNull( "command" ); } SqlConnection connection = command.Connection; // if the command doesn't have a connection set up, try to set one up on it's behalf if ( null == connection ) { using ( SqlConnection newConnection = new SqlConnection( "Context Connection=true" ) ) { newConnection.Open( ); // use try-finally to restore command's connection property to it's original state try { command.Connection = newConnection; command.ExecuteToPipe( _smiContext ); } finally { command.Connection = null; } } } else { // validate connection state if ( ConnectionState.Open != connection.State ) { throw ADP.ClosedConnectionError(); } // validate connection is current scope's connection SqlInternalConnectionSmi internalConnection = connection.InnerConnection as SqlInternalConnectionSmi; if ( null == internalConnection ) { throw SQL.SqlPipeCommandHookedUpToNonContextConnection( ); } command.ExecuteToPipe( _smiContext ); } } finally { ClearPipeBusy( ); } } // Equivalent to TSQL PRINT statement -- sends an info-only message. public void Send( string message ) { ADP.CheckArgumentNull(message, "message"); if ( SmiMetaData.MaxUnicodeCharacters < message.Length ) { throw SQL.SqlPipeMessageTooLong( message.Length ); } SetPipeBusy( ); try { EnsureNormalSendValid( "Send" ); _smiContext.SendMessageToPipe( message, _eventSink ); // Handle any errors that are reported. _eventSink.ProcessMessagesAndThrow(); } finally { ClearPipeBusy( ); } } // Send results from SqlDataReader public void Send( SqlDataReader reader ) { ADP.CheckArgumentNull(reader, "reader"); SetPipeBusy( ); try { EnsureNormalSendValid( "Send" ); do { SmiExtendedMetaData[] columnMetaData = reader.GetInternalSmiMetaData(); if (null != columnMetaData && 0 != columnMetaData.Length) { // using ( SmiRecordBuffer recordBuffer = _smiContext.CreateRecordBuffer(columnMetaData, _eventSink) ) { _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. _smiContext.SendResultsStartToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. try { while( reader.Read( ) ) { if (SmiContextFactory.Instance.NegotiatedSmiVersion >= SmiContextFactory.KatmaiVersion) { ValueUtilsSmi.FillCompatibleSettersFromReader(_eventSink, recordBuffer, new List(columnMetaData), reader); } else { ValueUtilsSmi.FillCompatibleITypedSettersFromReader(_eventSink, recordBuffer, columnMetaData, reader); } _smiContext.SendResultsRowToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. } } finally { _smiContext.SendResultsEndToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. } } } } while ( reader.NextResult( ) ); } finally { ClearPipeBusy( ); } } public void Send( SqlDataRecord record ) { ADP.CheckArgumentNull(record, "record"); SetPipeBusy( ); try { EnsureNormalSendValid( "Send" ); if (0 != record.FieldCount) { // SmiRecordBuffer recordBuffer; if (record.RecordContext == _smiContext) { recordBuffer = record.RecordBuffer; } else { // SendResultsRowToPipe() only takes a RecordBuffer created by an SmiContext SmiExtendedMetaData[] columnMetaData = record.InternalGetSmiMetaData(); recordBuffer = _smiContext.CreateRecordBuffer(columnMetaData, _eventSink); if (SmiContextFactory.Instance.NegotiatedSmiVersion >= SmiContextFactory.KatmaiVersion) { ValueUtilsSmi.FillCompatibleSettersFromRecord(_eventSink, recordBuffer, columnMetaData, record, null /* no default values */); } else { ValueUtilsSmi.FillCompatibleITypedSettersFromRecord(_eventSink, recordBuffer, columnMetaData, record); } } _smiContext.SendResultsStartToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. // If SendResultsStartToPipe succeeded, then SendResultsEndToPipe must be called. try { _smiContext.SendResultsRowToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. } finally { _smiContext.SendResultsEndToPipe( recordBuffer, _eventSink ); _eventSink.ProcessMessagesAndThrow(); // Handle any errors that are reported. } } } finally { ClearPipeBusy( ); } } public void SendResultsStart( SqlDataRecord record ) { ADP.CheckArgumentNull(record, "record"); SetPipeBusy( ); try { EnsureNormalSendValid( "SendResultsStart" ); SmiRecordBuffer recordBuffer = record.RecordBuffer; if (record.RecordContext == _smiContext) { recordBuffer = record.RecordBuffer; } else { recordBuffer = _smiContext.CreateRecordBuffer(record.InternalGetSmiMetaData(), _eventSink); // Only MetaData needed for sending start } _smiContext.SendResultsStartToPipe( recordBuffer, _eventSink ); // Handle any errors that are reported. _eventSink.ProcessMessagesAndThrow(); // remember sent buffer info so it can be used in send row/end. _recordBufferSent = recordBuffer; _metaDataSent = record.InternalGetMetaData(); } finally { ClearPipeBusy( ); } } public void SendResultsRow( SqlDataRecord record ) { ADP.CheckArgumentNull(record, "record"); SetPipeBusy( ); try { EnsureResultStarted( "SendResultsRow" ); if ( _hadErrorInResultSet ) { throw SQL.SqlPipeErrorRequiresSendEnd(); } // Assume error state unless cleared below _hadErrorInResultSet = true; SmiRecordBuffer recordBuffer; if (record.RecordContext == _smiContext) { recordBuffer = record.RecordBuffer; } else { SmiExtendedMetaData[] columnMetaData = record.InternalGetSmiMetaData(); recordBuffer = _smiContext.CreateRecordBuffer(columnMetaData, _eventSink); if (SmiContextFactory.Instance.NegotiatedSmiVersion >= SmiContextFactory.KatmaiVersion) { ValueUtilsSmi.FillCompatibleSettersFromRecord(_eventSink, recordBuffer, columnMetaData, record, null /* no default values */); } else { ValueUtilsSmi.FillCompatibleITypedSettersFromRecord(_eventSink, recordBuffer, columnMetaData, record); } } _smiContext.SendResultsRowToPipe( recordBuffer, _eventSink ); // Handle any errors that are reported. _eventSink.ProcessMessagesAndThrow(); // We successfully traversed the send, clear error state _hadErrorInResultSet = false; } finally { ClearPipeBusy( ); } } public void SendResultsEnd( ) { SetPipeBusy( ); try { EnsureResultStarted( "SendResultsEnd" ); _smiContext.SendResultsEndToPipe( _recordBufferSent, _eventSink ); // Once end called down to native code, assume end of resultset _metaDataSent = null; _recordBufferSent = null; _hadErrorInResultSet = false; // Handle any errors that are reported. _eventSink.ProcessMessagesAndThrow(); } finally { ClearPipeBusy( ); } } // This isn't speced, but it may not be a bad idea to implement... public bool IsSendingResults { get { return null != _metaDataSent; } } internal void OnOutOfScope( ) { _metaDataSent = null; _recordBufferSent = null; _hadErrorInResultSet = false; _isBusy = false; } // Pipe busy status. // Ensures user code cannot call any APIs while a send is in progress. // // Public methods must call this method before sending anything to the unmanaged pipe. // Once busy status is set, it must clear before returning from the calling method // ( i.e. clear should be in a finally block). private void SetPipeBusy( ) { if ( _isBusy ) { throw SQL.SqlPipeIsBusy( ); } _isBusy = true; } // Clear the pipe's busy status. private void ClearPipeBusy( ) { _isBusy = false; } // // State validation // One of the Ensure* validation methods should appear at the top of every public method // // Default validation method // Ensures Pipe is not currently transmitting a push-model resultset private void EnsureNormalSendValid( string methodName ) { if ( IsSendingResults ) { throw SQL.SqlPipeAlreadyHasAnOpenResultSet( methodName ); } } private void EnsureResultStarted( string methodName ) { if ( !IsSendingResults ) { throw SQL.SqlPipeDoesNotHaveAnOpenResultSet( methodName ); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RequestQueue.cs
- ModelItemExtensions.cs
- LoginUtil.cs
- AmbientProperties.cs
- SynchronizedDispatch.cs
- ArgumentOutOfRangeException.cs
- OleDbStruct.cs
- ScrollItemPattern.cs
- UserControlParser.cs
- FacetChecker.cs
- FieldBuilder.cs
- Timeline.cs
- FieldDescriptor.cs
- Encoder.cs
- oledbconnectionstring.cs
- CodeIdentifiers.cs
- HtmlTextBoxAdapter.cs
- XmlAttributeCollection.cs
- AbsoluteQuery.cs
- MsmqVerifier.cs
- ApplicationBuildProvider.cs
- RawStylusInputCustomDataList.cs
- ObjectSet.cs
- StringAnimationUsingKeyFrames.cs
- VectorCollection.cs
- DataGridViewImageColumn.cs
- HitTestWithPointDrawingContextWalker.cs
- LinqDataSourceContextEventArgs.cs
- CorePropertiesFilter.cs
- SchemaMapping.cs
- BasicViewGenerator.cs
- SynchronousSendBindingElement.cs
- ServerIdentity.cs
- LineSegment.cs
- AspNetSynchronizationContext.cs
- IndexOutOfRangeException.cs
- WeakReadOnlyCollection.cs
- EntryIndex.cs
- CommandDesigner.cs
- TableLayoutSettingsTypeConverter.cs
- CLSCompliantAttribute.cs
- ProviderUtil.cs
- LookupTables.cs
- PropertyEmitterBase.cs
- WaitHandle.cs
- SemanticResultKey.cs
- WindowsTokenRoleProvider.cs
- PersonalizationProviderHelper.cs
- PointCollection.cs
- NavigateEvent.cs
- SectionInformation.cs
- XmlSchemaSimpleTypeList.cs
- NameTable.cs
- BehaviorEditorPart.cs
- MethodRental.cs
- ClosableStream.cs
- InvalidCastException.cs
- DateTimeValueSerializer.cs
- CodeTypeReference.cs
- IisTraceWebEventProvider.cs
- ExpressionConverter.cs
- HashAlgorithm.cs
- DataGridCommandEventArgs.cs
- PerfCounters.cs
- TypeGeneratedEventArgs.cs
- EventHandlersStore.cs
- RenderingEventArgs.cs
- MembershipValidatePasswordEventArgs.cs
- ArgumentException.cs
- HttpListenerRequest.cs
- ProgressBarAutomationPeer.cs
- FromReply.cs
- PrePrepareMethodAttribute.cs
- ContextInformation.cs
- XMLDiffLoader.cs
- CoordinationService.cs
- CompositeDataBoundControl.cs
- BinaryObjectWriter.cs
- StylusSystemGestureEventArgs.cs
- DocumentSequence.cs
- XmlTextAttribute.cs
- BindingManagerDataErrorEventArgs.cs
- SqlDataSourceConfigureSortForm.cs
- StringUtil.cs
- XmlHierarchicalDataSourceView.cs
- ModelUIElement3D.cs
- KeyboardDevice.cs
- Behavior.cs
- HttpListenerException.cs
- IncrementalCompileAnalyzer.cs
- SqlFacetAttribute.cs
- WebPartDescriptionCollection.cs
- UnsafePeerToPeerMethods.cs
- SqlConnectionFactory.cs
- Set.cs
- Vector3DIndependentAnimationStorage.cs
- EventKeyword.cs
- Glyph.cs
- IpcServerChannel.cs
- SspiSafeHandles.cs