QueryResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / QueryResult.cs / 1305376 / QueryResult.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// query object
//  
//--------------------------------------------------------------------- 

namespace System.Data.Services.Client 
{
    using System;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.IO; 
#if !ASTORIA_LIGHT // Data.Services http stack 
    using System.Net;
#else 
    using System.Data.Services.Http;
#endif

    ///  
    /// Wrapper HttpWebRequest & HttWebResponse
    ///  
    internal class QueryResult : BaseAsyncResult 
    {
        /// Originating service request 
        internal readonly DataServiceRequest ServiceRequest;

        /// Originating WebRequest
        internal readonly HttpWebRequest Request; 

        /// reusuable async copy buffer 
        private static byte[] reusableAsyncCopyBuffer; 

        /// content to write to request stream 
        private MemoryStream requestStreamContent;

        /// active web request stream
        private Stream requestStream; 

        /// web response, closed when completed 
        private HttpWebResponse httpWebResponse; 

        /// async response stream, closed when completed 
        private Stream asyncResponseStream;

        /// buffer when copying async stream to response stream cache
        private byte[] asyncStreamCopyBuffer; 

        /// response stream, returned to other parts of the system 
        /// with async, the asyncResponseStream is copied into this stream 
        private Stream responseStream;
 
        /// copy of HttpWebResponse.ContentType
        private string contentType;

        /// copy of HttpWebResponse.ContentLength 
        private long contentLength;
 
        /// copy of HttpWebResponse.StatusCode 
        private HttpStatusCode statusCode;
 
        /// 
        /// does this own the response stream or does the container of this QueryAsyncResult?
        /// 
        private bool responseStreamOwner; 

        ///  
        /// if the BeginRead has been called with asyncStreamCopyBuffer, but EndRead has not. 
        /// do not return the buffer to general pool if any question of it being in use.
        ///  
        private bool usingBuffer;

#if StreamContainsBuffer
        /// does the responseStream contain the asyncStreamCopyBuffer? 
        /// optimize reading in to the async buffer without copying into separate response stream
        private bool responseStreamIsCopyBuffer; 
#endif 

        /// constructor 
        /// source object of async request
        /// async method name on source object
        /// Originating serviceRequest
        /// Originating WebRequest 
        /// user callback
        /// user state 
        internal QueryResult(object source, string method, DataServiceRequest serviceRequest, HttpWebRequest request, AsyncCallback callback, object state) 
            : base(source, method, callback, state)
        { 
            Debug.Assert(null != request, "null request");
            this.ServiceRequest = serviceRequest;
            this.Request = request;
            this.Abortable = request; 
        }
 
        #region HttpResponse wrapper - ContentLength, ContentType, StatusCode 

        /// HttpWebResponse.ContentLength 
        internal long ContentLength
        {
            get { return this.contentLength; }
        } 

        /// HttpWebResponse.ContentType 
        internal string ContentType 
        {
            get { return this.contentType; } 
        }

        /// HttpWebResponse.StatusCode
        internal HttpStatusCode StatusCode 
        {
            get { return this.statusCode; } 
        } 

        #endregion 

        /// 
        /// Ends the asynchronous query request.
        ///  
        /// Element type of the result.
        /// Source object of async request. 
        /// The asyncResult being ended. 
        /// Data service response.
        internal static QueryResult EndExecute(object source, IAsyncResult asyncResult) 
        {
            QueryResult response = null;

            try 
            {
                response = BaseAsyncResult.EndExecute(source, "Execute", asyncResult); 
            } 
            catch (InvalidOperationException ex)
            { 
                response = asyncResult as QueryResult;
                Debug.Assert(response != null, "response != null, BaseAsyncResult.EndExecute() would have thrown a different exception otherwise.");

                QueryOperationResponse operationResponse = response.GetResponse(MaterializeAtom.EmptyResults); 
                if (operationResponse != null)
                { 
                    operationResponse.Error = ex; 
                    throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse);
                } 

                throw;
            }
 
            return response;
        } 
 
        /// wrapper for HttpWebResponse.GetResponseStream
        /// stream 
        internal Stream GetResponseStream()
        {
            return this.responseStream;
        } 

        /// start the asynchronous request 
        internal void BeginExecute() 
        {
            try 
            {
                IAsyncResult asyncResult;
#if false
                if ((null != requestContent) && (0 < requestContent.Length)) 
                {
                    requestContent.Position = 0; 
                    this.requestStreamContent = requestContent; 
                    this.Request.ContentLength = requestContent.Length;
                    asyncResult = this.Request.BeginGetRequestStream(QueryAsyncResult.AsyncEndGetRequestStream, this); 
                }
                else
#endif
                { 
                    asyncResult = BaseAsyncResult.InvokeAsync(this.Request.BeginGetResponse, QueryResult.AsyncEndGetResponse, this);
                } 
 
                this.CompletedSynchronously &= asyncResult.CompletedSynchronously;
            } 
            catch (Exception e)
            {
                this.HandleFailure(e);
                throw; 
            }
            finally 
            { 
                this.HandleCompleted();
            } 

            Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted");
        }
 
#if !ASTORIA_LIGHT
        /// Synchronous web request 
        internal void Execute() 
        {
            try 
            {
#if false
                if ((null != requestContent) && (0 < requestContent.Length))
                { 
                    using (System.IO.Stream stream = Util.NullCheck(this.Request.GetRequestStream(), InternalError.InvalidGetRequestStream))
                    { 
                        byte[] buffer = requestContent.GetBuffer(); 
                        int bufferOffset = checked((int)requestContent.Position);
                        int bufferLength = checked((int)requestContent.Length) - bufferOffset; 

                        // the following is useful in the debugging Immediate Window
                        // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength);
                        stream.Write(buffer, bufferOffset, bufferLength); 
                    }
                } 
#endif 

                HttpWebResponse response = null; 
                try
                {
                    response = (HttpWebResponse)this.Request.GetResponse();
                } 
                catch (WebException ex)
                { 
                    response = (HttpWebResponse)ex.Response; 
                    if (null == response)
                    { 
                        throw;
                    }
                }
 
                this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse));
 
                if (HttpStatusCode.NoContent != this.StatusCode) 
                {
                    using (Stream stream = this.httpWebResponse.GetResponseStream()) 
                    {
                        if (null != stream)
                        {
                            Stream copy = this.GetAsyncResponseStreamCopy(); 
                            this.responseStream = copy;
 
                            Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer(); 

                            long copied = WebUtil.CopyStream(stream, copy, ref buffer); 
                            if (this.responseStreamOwner)
                            {
                                if (0 == copied)
                                { 
                                    this.responseStream = null;
                                } 
                                else if (copy.Position < copy.Length) 
                                {   // In Silverlight, generally 3 bytes less than advertised by ContentLength are read
                                    ((MemoryStream)copy).SetLength(copy.Position); 
                                }
                            }

                            this.PutAsyncResponseStreamCopyBuffer(buffer); 
                        }
                    } 
                } 
            }
            catch (Exception e) 
            {
                this.HandleFailure(e);
                throw;
            } 
            finally
            { 
                this.SetCompleted(); 
                this.CompletedRequest();
            } 

            if (null != this.Failure)
            {
                throw this.Failure; 
            }
        } 
#endif 

        ///  
        /// Returns the response for the request.
        /// 
        /// materialized results for the request.
        /// element type of the results. 
        /// returns the instance of QueryOperationResponse containing the response.
        internal QueryOperationResponse GetResponse(MaterializeAtom results) 
        { 
            if (this.httpWebResponse != null)
            { 
                Dictionary headers = WebUtil.WrapResponseHeaders(this.httpWebResponse);
                QueryOperationResponse response = new QueryOperationResponse(headers, this.ServiceRequest, results);
                response.StatusCode = (int)this.httpWebResponse.StatusCode;
                return response; 
            }
 
            return null; 
        }
 
        /// 
        /// Returns the response for the request.
        /// 
        /// materialized results for the request. 
        /// element type of the results.
        /// returns the instance of QueryOperationResponse containing the response. 
        internal QueryOperationResponse GetResponseWithType(MaterializeAtom results, Type elementType) 
        {
            if (this.httpWebResponse != null) 
            {
                Dictionary headers = WebUtil.WrapResponseHeaders(this.httpWebResponse);
                QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results);
                response.StatusCode = (int)this.httpWebResponse.StatusCode; 
                return response;
            } 
 
            return null;
        } 

        /// 
        /// Create materializer on top of response stream
        ///  
        /// The data service context
        /// Precompiled projection plan (possibly null). 
        /// A materializer instance ready to deserialize ther result 
        internal MaterializeAtom GetMaterializer(DataServiceContext context, ProjectionPlan plan)
        { 
            Debug.Assert(this.IsCompletedInternally, "request hasn't completed yet");

            MaterializeAtom materializer;
            if (HttpStatusCode.NoContent != this.StatusCode) 
            {
                materializer = DataServiceRequest.Materialize(context, this.ServiceRequest.QueryComponents, plan, this.ContentType, this.GetResponseStream()); 
            } 
            else
            { 
                materializer = MaterializeAtom.EmptyResults;
            }

            return materializer; 
        }
 
        ///  
        /// Processes the result for successfull request and produces the actual result of the request.
        ///  
        /// Element type of the result.
        /// The data service context.
        /// The plan to use for the projection, if available in precompiled form.
        /// A instance of QueryResponseResult created on top of of the request. 
        internal QueryOperationResponse ProcessResult(DataServiceContext context, ProjectionPlan plan)
        { 
            MaterializeAtom materializeAtom = DataServiceRequest.Materialize(context, this.ServiceRequest.QueryComponents, plan, this.ContentType, this.GetResponseStream()); 
            return this.GetResponse(materializeAtom);
        } 

        /// cleanup work to do once the request has completed
        protected override void CompletedRequest()
        { 
            Util.Dispose(ref this.asyncResponseStream);
            Util.Dispose(ref this.requestStream); 
            Util.Dispose(ref this.requestStreamContent); 

            byte[] buffer = this.asyncStreamCopyBuffer; 
            this.asyncStreamCopyBuffer = null;
#if StreamContainsBuffer
            if (!this.responseStreamIsCopyBuffer)
#endif 
            if ((null != buffer) && !this.usingBuffer)
            { 
                this.PutAsyncResponseStreamCopyBuffer(buffer); 
            }
 
            if (this.responseStreamOwner)
            {
                if (null != this.responseStream)
                { 
                    this.responseStream.Position = 0;
                } 
            } 

            Debug.Assert(null != this.httpWebResponse || null != this.Failure, "should have response or exception"); 
            if (null != this.httpWebResponse)
            {
                // we've cached off what we need, headers still accessible after close
                this.httpWebResponse.Close(); 

                Exception ex = DataServiceContext.HandleResponse(this.StatusCode, this.httpWebResponse.Headers[XmlConstants.HttpDataServiceVersion], this.GetResponseStream, false); 
                if (null != ex) 
                {
                    this.HandleFailure(ex); 
                }
            }
        }
 
        /// get stream which of copy buffer (via response stream) will be copied into
        /// writtable stream, happens before GetAsyncResponseStreamCopyBuffer 
        protected virtual Stream GetAsyncResponseStreamCopy() 
        {
            this.responseStreamOwner = true; 

            long length = this.contentLength;
            if ((0 < length) && (length <= Int32.MaxValue))
            { 
                Debug.Assert(null == this.asyncStreamCopyBuffer, "not expecting buffer");
 
#if StreamContainsBuffer 
                byte[] buffer = new byte[(int)length];
                if (length < UInt16.MaxValue) 
                {   // larger than this appears to cause trouble, specifically tested with 2619442
                    responseStreamIsCopyBuffer = true;
                    this.asyncStreamCopyBuffer = buffer;
                } 
                return new MemoryStream(buffer, 0, buffer.Length, true, true);
#else 
                // SQLBU 644097 - if more content is returned than specified we want the memory 
                // stream to be expandable which doesn't happen if you preallocate a buffer
                return new MemoryStream((int)length); 
#endif
            }

            return new MemoryStream(); 
        }
 
        /// get buffer which response stream will be copied into 
        /// writtable stream
        protected virtual byte[] GetAsyncResponseStreamCopyBuffer() 
        {   // consider having a cache of these buffers since they will be pinned
            Debug.Assert(null == this.asyncStreamCopyBuffer, "non-null this.asyncStreamCopyBuffer");
            return System.Threading.Interlocked.Exchange(ref reusableAsyncCopyBuffer, null) ?? new byte[8000];
        } 

        /// returning a buffer after being done with it 
        /// buffer to return 
        protected virtual void PutAsyncResponseStreamCopyBuffer(byte[] buffer)
        { 
            reusableAsyncCopyBuffer = buffer;
        }

        /// set the http web response 
        /// response object
        protected virtual void SetHttpWebResponse(HttpWebResponse response) 
        { 
            this.httpWebResponse = response;
            this.statusCode = response.StatusCode; 
            this.contentLength = response.ContentLength;
            this.contentType = response.ContentType;
        }
 
#if false
        /// handle request.BeginGetRequestStream with request.EndGetRquestStream and then write out request stream 
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetRequestStream(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            try
            { 
                int step = CompleteCheck(state, InternalError.InvalidEndGetRequestCompleted);
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetRequestStream 
 
                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetRequestStreamRequest);
 
                Stream stream = Util.NullCheck(httpWebRequest.EndGetRequestStream(asyncResult), InternalError.InvalidEndGetRequestStreamStream);
                state.requestStream = stream;

                MemoryStream memoryStream = Util.NullCheck(state.requestStreamContent, InternalError.InvalidEndGetRequestStreamContent); 
                byte[] buffer = memoryStream.GetBuffer();
                int bufferOffset = checked((int)memoryStream.Position); 
                int bufferLength = checked((int)memoryStream.Length) - bufferOffset; 
                if ((null == buffer) || (0 == bufferLength))
                { 
                    Error.ThrowInternalError(InternalError.InvalidEndGetRequestStreamContentLength);
                }

                // the following is useful in the debugging Immediate Window 
                // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength);
                asyncResult = stream.BeginWrite(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndWrite, state); 
 
                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep);
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginWrite 
            }
            catch (Exception e)
            {
                if (state.HandleFailure(e)) 
                {
                    throw; 
                } 
            }
            finally 
            {
                state.HandleCompleted();
            }
        } 

        /// handle reqestStream.BeginWrite with requestStream.EndWrite then BeginGetResponse 
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndWrite(IAsyncResult asyncResult) 
        {
            QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult;
            try
            { 
                int step = CompleteCheck(state, InternalError.InvalidEndWriteCompleted);
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginWrite 
 
                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndWriteRequest);
 
                Stream stream = Util.NullCheck(state.requestStream, InternalError.InvalidEndWriteStream);
                stream.EndWrite(asyncResult);

                state.requestStream = null; 
                stream.Dispose();
 
                stream = state.requestStreamContent; 
                if (null != stream)
                { 
                    state.requestStreamContent = null;
                    stream.Dispose();
                }
 
                asyncResult = httpWebRequest.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, state);
 
                bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); 
                state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginGetResponse
            } 
            catch (Exception e)
            {
                if (state.HandleFailure(e))
                { 
                    throw;
                } 
            } 
            finally
            { 
                state.HandleCompleted();
            }
        }
#endif 

        /// handle request.BeginGetResponse with request.EndGetResponse and then copy response stream 
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")]
        private static void AsyncEndGetResponse(IAsyncResult asyncResult) 
        {
            Debug.Assert(asyncResult != null && asyncResult.IsCompleted, "asyncResult.IsCompleted");
            QueryResult state = asyncResult.AsyncState as QueryResult;
            try 
            {
                CompleteCheck(state, InternalError.InvalidEndGetResponseCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetResponse 

                HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetResponseRequest); 

                // the httpWebResponse is kept for batching, discarded by non-batch
                HttpWebResponse response = null;
                try 
                {
                    response = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult); 
                } 
                catch (WebException e)
                { 
                    response = (HttpWebResponse)e.Response;
                    if (null == response)
                    {
                        throw; 
                    }
                } 
 
                state.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidEndGetResponseResponse));
                Debug.Assert(null == state.asyncResponseStream, "non-null asyncResponseStream"); 

                Stream stream = null;
                if (HttpStatusCode.NoContent != response.StatusCode)
                { 
                    stream = response.GetResponseStream();
                    state.asyncResponseStream = stream; 
                } 

                if ((null != stream) && stream.CanRead) 
                {
                    if (null == state.responseStream)
                    {   // this is the stream we copy the reponse to
                        state.responseStream = Util.NullCheck(state.GetAsyncResponseStreamCopy(), InternalError.InvalidAsyncResponseStreamCopy); 
                    }
 
                    if (null == state.asyncStreamCopyBuffer) 
                    {   // this is the buffer we read into and copy out of
                        state.asyncStreamCopyBuffer = Util.NullCheck(state.GetAsyncResponseStreamCopyBuffer(), InternalError.InvalidAsyncResponseStreamCopyBuffer); 
                    }

                    // Make async calls to read the response stream
                    QueryResult.ReadResponseStream(state); 
                }
                else 
                { 
                    state.SetCompleted();
                } 
            }
            catch (Exception e)
            {
                if (state.HandleFailure(e)) 
                {
                    throw; 
                } 
            }
            finally 
            {
                state.HandleCompleted();
            }
        } 

        ///  
        /// Make async calls to read the response stream. 
        /// 
        /// query result to populate 
        private static void ReadResponseStream(QueryResult queryResult)
        {
            IAsyncResult asyncResult;
 
            byte[] buffer = queryResult.asyncStreamCopyBuffer;
            Stream stream = queryResult.asyncResponseStream; 
            do 
            {
                int bufferOffset, bufferLength; 
#if StreamContainsBuffer
                if (state.responseStreamIsCopyBuffer)
                {   // we may have asked for, but not received the entire stream
                    bufferOffset = checked((int)state.responseStream.Position); 
                    bufferLength = buffer.Length - bufferOffset;
                } 
                else 
#endif
                { 
                    bufferOffset = 0;
                    bufferLength = buffer.Length;
                }
 
                queryResult.usingBuffer = true;
                asyncResult = BaseAsyncResult.InvokeAsync(stream.BeginRead, buffer, bufferOffset, bufferLength, QueryResult.AsyncEndRead, queryResult); 
                queryResult.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead 
            }
            while (asyncResult.CompletedSynchronously && !queryResult.IsCompletedInternally && stream.CanRead); 

            Debug.Assert(!queryResult.CompletedSynchronously || queryResult.IsCompletedInternally, "AsyncEndGetResponse !IsCompleted");
        }
 
        /// handle responseStream.BeginRead with responseStream.EndRead
        /// async result 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] 
        private static void AsyncEndRead(IAsyncResult asyncResult)
        { 
            Debug.Assert(asyncResult != null && asyncResult.IsCompleted, "asyncResult.IsCompleted");
            QueryResult state = asyncResult.AsyncState as QueryResult;
            int count = 0;
            try 
            {
                CompleteCheck(state, InternalError.InvalidEndReadCompleted); 
                state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead 

                Stream stream = Util.NullCheck(state.asyncResponseStream, InternalError.InvalidEndReadStream); 
                Stream outputResponse = Util.NullCheck(state.responseStream, InternalError.InvalidEndReadCopy);
                byte[] buffer = Util.NullCheck(state.asyncStreamCopyBuffer, InternalError.InvalidEndReadBuffer);

                count = stream.EndRead(asyncResult); 
                state.usingBuffer = false;
                if (0 < count) 
                { 
#if StreamContainsBuffer
                    if (state.responseStreamIsCopyBuffer) 
                    {   // we may have asked for, but not received the entire stream
                        outputResponse.Position = outputResponse.Position + count;
                    }
                    else 
#endif
                    { 
                        outputResponse.Write(buffer, 0, count); 
                    }
                } 

                if (0 < count && 0 < buffer.Length && stream.CanRead)
                {
                    if (!asyncResult.CompletedSynchronously) 
                    {
                        // if CompletedSynchronously then caller will call and we reduce risk of stack overflow 
                        QueryResult.ReadResponseStream(state); 
                    }
                } 
                else
                {
#if StreamContainsBuffer
                    Debug.Assert(!state.responseStreamIsCopyBuffer || (outputResponse.Position == outputResponse.Length), "didn't read expected count"); 
#endif
                    // Debug.Assert(state.ContentLength < 0 || outputResponse.Length == state.ContentLength, "didn't read expected ContentLength"); 
                    if (outputResponse.Position < outputResponse.Length) 
                    {
                        // In Silverlight, generally 3 bytes less than advertised by ContentLength are read 
                        ((MemoryStream)outputResponse).SetLength(outputResponse.Position);
                    }

                    state.SetCompleted(); 
                }
            } 
            catch (Exception e) 
            {
                if (state.HandleFailure(e)) 
                {
                    throw;
                }
            } 
            finally
            { 
                state.HandleCompleted(); 
            }
        } 

        /// verify non-null and not completed
        /// async result
        /// error code if null or completed 
        private static void CompleteCheck(QueryResult pereq, InternalError errorcode)
        { 
            if ((null == pereq) || (pereq.IsCompletedInternally && !pereq.IsAborted)) 
            {
                // if aborting, let the request throw its abort code 
                Error.ThrowInternalError(errorcode);
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK