Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Data / Microsoft / SqlServer / Server / sqlpipe.cs / 1 / 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) { // SQLBUDT #340528 -- don't send empty results. 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) { // SQLBUDT #340564 -- don't send empty records. 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. // //[....] //[....] //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) { // SQLBUDT #340528 -- don't send empty results. 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) { // SQLBUDT #340564 -- don't send empty records. 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridViewRowPostPaintEventArgs.cs
- CategoryValueConverter.cs
- ISAPIRuntime.cs
- EntityTemplateUserControl.cs
- SimpleRecyclingCache.cs
- SyntaxCheck.cs
- HtmlControlPersistable.cs
- FileVersionInfo.cs
- TextComposition.cs
- GregorianCalendarHelper.cs
- SQLRoleProvider.cs
- Control.cs
- SignedXmlDebugLog.cs
- RangeValidator.cs
- _Events.cs
- Literal.cs
- Quaternion.cs
- InitializerFacet.cs
- TemplateControlCodeDomTreeGenerator.cs
- NullRuntimeConfig.cs
- EnumDataContract.cs
- WindowsSolidBrush.cs
- TopClause.cs
- TraceShell.cs
- Registry.cs
- UrlPath.cs
- SystemColors.cs
- TypeDependencyAttribute.cs
- SocketPermission.cs
- ProvideValueServiceProvider.cs
- ThicknessAnimationBase.cs
- SubstitutionResponseElement.cs
- BindingContext.cs
- DeclaredTypeElement.cs
- ProfilePropertySettingsCollection.cs
- SharedPersonalizationStateInfo.cs
- TextBoxBase.cs
- LineUtil.cs
- XmlDataProvider.cs
- ByteStreamMessageEncoderFactory.cs
- MaterialGroup.cs
- DesignerSerializationOptionsAttribute.cs
- CapabilitiesRule.cs
- DoubleUtil.cs
- ListBindableAttribute.cs
- WebColorConverter.cs
- CodeDelegateCreateExpression.cs
- NativeMethods.cs
- SerializationEventsCache.cs
- DataGridRelationshipRow.cs
- CustomWebEventKey.cs
- BamlLocalizationDictionary.cs
- RemoteWebConfigurationHost.cs
- PageParserFilter.cs
- WsdlParser.cs
- PrimitiveDataContract.cs
- xmlfixedPageInfo.cs
- Point.cs
- GreaterThanOrEqual.cs
- DeferredSelectedIndexReference.cs
- ImmutableCommunicationTimeouts.cs
- PickBranch.cs
- GPRECTF.cs
- GenericIdentity.cs
- FrameworkElement.cs
- LocalIdCollection.cs
- IndentedTextWriter.cs
- GeneralEndpointIdentity.cs
- BamlResourceContent.cs
- ToolStripManager.cs
- ExpressionNode.cs
- AdornerHitTestResult.cs
- XmlValidatingReader.cs
- SerializationHelper.cs
- CannotUnloadAppDomainException.cs
- ContainerUtilities.cs
- ControlType.cs
- DataViewListener.cs
- SmtpDigestAuthenticationModule.cs
- RuntimeHandles.cs
- relpropertyhelper.cs
- WebPartManagerInternals.cs
- ValidationError.cs
- ConfigPathUtility.cs
- TextBlockAutomationPeer.cs
- PropertyGrid.cs
- TreeNodeEventArgs.cs
- EventManager.cs
- WindowsFormsSectionHandler.cs
- Stylesheet.cs
- TextTreeObjectNode.cs
- NameValuePermission.cs
- SimpleTypeResolver.cs
- shaperfactoryquerycachekey.cs
- ListViewItem.cs
- ExtenderProvidedPropertyAttribute.cs
- Property.cs
- DefinitionProperties.cs
- GeneralTransform2DTo3D.cs
- AddInToken.cs