Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / Microsoft / SqlServer / Server / sqlpipe.cs / 1305376 / 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. public 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
- MaterialGroup.cs
- ManipulationPivot.cs
- smtpconnection.cs
- EntitySqlQueryBuilder.cs
- Enlistment.cs
- MD5CryptoServiceProvider.cs
- TypeUnloadedException.cs
- ArrayElementGridEntry.cs
- WindowsServiceCredential.cs
- PackagePart.cs
- ByteKeyFrameCollection.cs
- ConsoleCancelEventArgs.cs
- XmlDocumentType.cs
- XhtmlTextWriter.cs
- ZipPackage.cs
- Variant.cs
- parserscommon.cs
- EditingScope.cs
- RowBinding.cs
- PaperSize.cs
- WebUtil.cs
- IndexedEnumerable.cs
- RealProxy.cs
- SchemaExporter.cs
- DesignerAttribute.cs
- PersonalizationProviderHelper.cs
- UIElement3D.cs
- StylusDevice.cs
- EditorZone.cs
- MatrixKeyFrameCollection.cs
- StringUtil.cs
- BamlBinaryWriter.cs
- MultiTrigger.cs
- FixedSOMImage.cs
- UserControl.cs
- PointHitTestResult.cs
- ChangesetResponse.cs
- CfgRule.cs
- Clock.cs
- RowCache.cs
- RegexStringValidator.cs
- PermissionSet.cs
- ScaleTransform3D.cs
- WaitingCursor.cs
- UrlMappingCollection.cs
- COM2FontConverter.cs
- InvalidComObjectException.cs
- compensatingcollection.cs
- ExpressionBuilder.cs
- WebPartCloseVerb.cs
- SqlConnectionFactory.cs
- BaseTransportHeaders.cs
- XmlNullResolver.cs
- XmlCompatibilityReader.cs
- StandardBindingElement.cs
- UnsafeNativeMethodsMilCoreApi.cs
- StreamAsIStream.cs
- BamlResourceSerializer.cs
- NameValueCollection.cs
- BamlRecordReader.cs
- FlowDocumentReader.cs
- _UriTypeConverter.cs
- NavigationPropertyEmitter.cs
- ItemCheckedEvent.cs
- BasicHttpSecurityElement.cs
- SchemaDeclBase.cs
- FactoryId.cs
- StateMachineExecutionState.cs
- FormsAuthentication.cs
- CollectionChangeEventArgs.cs
- XslAst.cs
- XsltArgumentList.cs
- XmlSchemaNotation.cs
- SafeMarshalContext.cs
- AsymmetricAlgorithm.cs
- SystemEvents.cs
- UntypedNullExpression.cs
- CombinedGeometry.cs
- Size.cs
- RoleManagerSection.cs
- HttpWriter.cs
- BooleanToVisibilityConverter.cs
- entityreference_tresulttype.cs
- DesignTimeSiteMapProvider.cs
- LinearGradientBrush.cs
- elementinformation.cs
- AvtEvent.cs
- SqlMethodCallConverter.cs
- SizeAnimation.cs
- ChannelReliableSession.cs
- ComponentEditorPage.cs
- TypeRefElement.cs
- DataGridViewCheckBoxColumn.cs
- JsonGlobals.cs
- Contracts.cs
- _DomainName.cs
- thaishape.cs
- ConnectionsZoneAutoFormat.cs
- TreeWalker.cs
- PenThreadWorker.cs