public void ShortIntegrationTestToValidateEntryShouldBeRead() { var odataEntry = new ODataEntry() { Id = new Uri("http://services.odata.org/OData/OData.svc/Customers(0)") }; odataEntry.Properties = new ODataProperty[] { new ODataProperty() { Name = "ID", Value = 0 }, new ODataProperty() { Name = "Description", Value = "Simple Stuff" } }; var clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V4); var context = new DataServiceContext(); MaterializerEntry.CreateEntry(odataEntry, ODataFormat.Atom, true, clientEdmModel); var materializerContext = new TestMaterializerContext() {Model = clientEdmModel, Context = context}; var adapter = new EntityTrackingAdapter(new TestEntityTracker(), MergeOption.OverwriteChanges, clientEdmModel, context); QueryComponents components = new QueryComponents(new Uri("http://foo.com/Service"), new Version(4, 0), typeof(Customer), null, new Dictionary<Expression, Expression>()); var entriesMaterializer = new ODataEntriesEntityMaterializer(new ODataEntry[] { odataEntry }, materializerContext, adapter, components, typeof(Customer), null, ODataFormat.Atom); var customersRead = new List<Customer>(); // This line will call ODataEntityMaterializer.ReadImplementation() which will reconstruct the entity, and will get non-public setter called. while (entriesMaterializer.Read()) { customersRead.Add(entriesMaterializer.CurrentValue as Customer); } customersRead.Should().HaveCount(1); customersRead[0].ID.Should().Be(0); customersRead[0].Description.Should().Be("Simple Stuff"); }
/// <summary> /// Initializes a new <see cref="QueryComponents"/> instance that can /// be used for this continuation. /// </summary> /// <returns>A new initializes <see cref="QueryComponents"/>.</returns> internal QueryComponents CreateQueryComponents() { // DSV needs to be 2.0 since $skiptoken will be on the uri. QueryComponents result = new QueryComponents(this.NextLinkUri, Util.ODataVersionEmpty, this.Plan.LastSegmentType, null, null); return(result); }
/// <summary> /// Creates the result object for the specified query parameters. /// </summary> /// <param name="source">The source object for the request.</param> /// <param name="context">The data service context.</param> /// <param name="callback">The AsyncCallback delegate.</param> /// <param name="state">The state object for the callback.</param> /// <param name="method">async method name at the source.</param> /// <returns>Result representing the create request. The request has not been initiated yet.</returns> private QueryResult CreateExecuteResult(object source, DataServiceContext context, AsyncCallback callback, object state, string method) { Debug.Assert(context != null, "context is null"); QueryComponents qc = this.QueryComponents(context.Model); RequestInfo requestInfo = new RequestInfo(context); Debug.Assert( string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0 || string.CompareOrdinal(XmlConstants.HttpMethodGet, qc.HttpMethod) == 0 || string.CompareOrdinal(XmlConstants.HttpMethodDelete, qc.HttpMethod) == 0, "Only get, post and delete are supported in the execute pipeline, which should have been caught earlier"); if (qc.UriOperationParameters != null) { Debug.Assert(qc.UriOperationParameters.Any(), "qc.UriOperationParameters.Any()"); Serializer serializer = new Serializer(requestInfo); this.RequestUri = serializer.WriteUriOperationParametersToUri(this.RequestUri, qc.UriOperationParameters); } HeaderCollection headers = new HeaderCollection(); if (string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0) { if (qc.BodyOperationParameters == null) { // set the content length to be 0 if there are no operation parameters. headers.SetHeader(XmlConstants.HttpContentLength, "0"); } else { context.Format.SetRequestContentTypeForOperationParameters(headers); } } // Validate and set the request DSV and MDSV header headers.SetRequestVersion(qc.Version, requestInfo.MaxProtocolVersionAsVersion); requestInfo.Format.SetRequestAcceptHeaderForQuery(headers, qc); // We currently do not have a descriptor to expose to the user for invoking something through Execute. Ideally we could expose an OperationDescriptor. ODataRequestMessageWrapper requestMessage = new RequestInfo(context).WriteHelper.CreateRequestMessage(context.CreateRequestArgsAndFireBuildingRequest(qc.HttpMethod, this.RequestUri, headers, context.HttpStack, null /*descriptor*/)); requestMessage.FireSendingRequest2(null /*descriptor*/); if (qc.BodyOperationParameters != null) { Debug.Assert(string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0, "qc.HttpMethod == XmlConstants.HttpMethodPost"); Debug.Assert(qc.BodyOperationParameters.Any(), "unexpected body operation parameter count of zero."); Serializer serializer = new Serializer(requestInfo, context.EntityParameterSendOption); serializer.WriteBodyOperationParameters(qc.BodyOperationParameters, requestMessage); // pass in the request stream so that request payload can be written to the http webrequest. return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state, requestMessage.CachedRequestStream)); } return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state)); }
/// <summary>Create a request for a specific Uri</summary> /// <param name="requestUri">The URI for the request.</param> /// <param name="queryComponents">The query components for the request</param> /// <param name="plan">Projection plan to reuse (possibly null).</param> internal DataServiceRequest(Uri requestUri, QueryComponents queryComponents, ProjectionPlan plan) : this(requestUri) { Debug.Assert(requestUri != null, "requestUri != null"); Debug.Assert(queryComponents != null, "queryComponents != null"); this.queryComponents = queryComponents; this.plan = plan; }
/// <summary> /// gets the query components for the query after translating /// </summary> /// <returns>QueryComponents for query</returns> private QueryComponents Translate() { if (this.queryComponents == null) { this.queryComponents = this.queryProvider.Translate(this.queryExpression); } return(this.queryComponents); }
/// <summary> /// Synchronously executes the query and returns the value. /// </summary> /// <param name="context">The context.</param> /// <param name="parseQueryResultFunc">A function to process the query result.</param> /// <returns>The query result</returns> internal TElement GetValue <TElement>(DataServiceContext context, Func <QueryResult, TElement> parseQueryResultFunc) { Debug.Assert(context != null, "context is null"); QueryComponents queryComponents = this.QueryComponents(context.Model); Version requestVersion = queryComponents.Version; if (requestVersion == null) { requestVersion = Util.ODataVersion4; } Uri requestUri = queryComponents.Uri; DataServiceRequest <TElement> serviceRequest = new DataServiceRequest <TElement>(requestUri, queryComponents, null); HeaderCollection headers = new HeaderCollection(); // Validate and set the request DSV header headers.SetRequestVersion(requestVersion, context.MaxProtocolVersionAsVersion); context.Format.SetRequestAcceptHeaderForCount(headers); string httpMethod = XmlConstants.HttpMethodGet; ODataRequestMessageWrapper request = context.CreateODataRequestMessage( context.CreateRequestArgsAndFireBuildingRequest(httpMethod, requestUri, headers, context.HttpStack, null /*descriptor*/), null /*descriptor*/); QueryResult queryResult = new QueryResult(this, Util.ExecuteMethodName, serviceRequest, request, new RequestInfo(context), null, null); try { queryResult.ExecuteQuery(); if (HttpStatusCode.NoContent != queryResult.StatusCode) { TElement parsedResult = parseQueryResultFunc(queryResult); return(parsedResult); } else { throw new DataServiceQueryException(Strings.DataServiceRequest_FailGetValue, queryResult.Failure); } } catch (InvalidOperationException ex) { QueryOperationResponse operationResponse; operationResponse = queryResult.GetResponse <TElement>(MaterializeAtom.EmptyResults); if (operationResponse != null) { operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } throw; } }
/// <summary> /// Initializes a new instance of the <see cref="ODataEntriesEntityMaterializer" /> class. /// </summary> /// <param name="entries">The entries.</param> /// <param name="materializerContext">The materializer context.</param> /// <param name="entityTrackingAdapter">The entity tracking adapter.</param> /// <param name="queryComponents">The query components.</param> /// <param name="expectedType">The expected type.</param> /// <param name="materializeEntryPlan">The materialize entry plan.</param> /// <param name="format">The format.</param> public ODataEntriesEntityMaterializer( IEnumerable<ODataEntry> entries, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan, ODataFormat format) : base(materializerContext, entityTrackingAdapter, queryComponents, expectedType, materializeEntryPlan) { this.format = format; this.feedEntries = entries.GetEnumerator(); }
/// <summary>The QueryComponents associated with this request</summary> /// <param name="model">The client model.</param> /// <returns>an instance of QueryComponents.</returns> internal override QueryComponents QueryComponents(ClientEdmModel model) { if (this.queryComponents == null) { Type elementType = typeof(TElement); // for 1..* navigation properties we need the type of the entity of the collection that is being navigated to. Otherwise we use TElement. elementType = PrimitiveType.IsKnownType(elementType) || WebUtil.IsCLRTypeCollection(elementType, model) ? elementType : TypeSystem.GetElementType(elementType); this.queryComponents = new QueryComponents(this.requestUri, Util.ODataVersionEmpty, elementType, null, null); } return(this.queryComponents); }
/// <summary> /// Initializes a new instance of the <see cref="ODataReaderEntityMaterializer" /> class. /// </summary> /// <param name="odataMessageReader">The odata message reader.</param> /// <param name="reader">The reader.</param> /// <param name="materializerContext">The materializer context.</param> /// <param name="entityTrackingAdapter">The entity tracking adapter.</param> /// <param name="queryComponents">The query components.</param> /// <param name="expectedType">The expected type.</param> /// <param name="materializeEntryPlan">The materialize entry plan.</param> public ODataReaderEntityMaterializer( ODataMessageReader odataMessageReader, ODataReaderWrapper reader, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan) : base(materializerContext, entityTrackingAdapter, queryComponents, expectedType, materializeEntryPlan) { this.messageReader = odataMessageReader; this.feedEntryAdapter = new FeedAndEntryMaterializerAdapter(odataMessageReader, reader, materializerContext.Model, entityTrackingAdapter.MergeOption); }
/// <summary> /// constructor /// </summary> /// <param name="responseInfo">originating context</param> /// <param name="entries">entries that needs to be materialized.</param> /// <param name="elementType">result type.</param> /// <param name="format">The format of the response being materialized from.</param> internal MaterializeAtom(ResponseInfo responseInfo, IEnumerable <ODataResource> entries, Type elementType, ODataFormat format) { this.responseInfo = responseInfo; this.elementType = elementType; this.expectingPrimitiveValue = PrimitiveType.IsKnownNullableType(elementType); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingPrimitiveValue, this.elementType, responseInfo.Model, out implementationType); QueryComponents qc = new QueryComponents(null, Util.ODataVersionEmpty, elementType, null, null); ODataMaterializerContext context = new ODataMaterializerContext(responseInfo); EntityTrackingAdapter entityTrackingAdapter = new EntityTrackingAdapter(responseInfo.EntityTracker, responseInfo.MergeOption, responseInfo.Model, responseInfo.Context); this.materializer = new ODataEntriesEntityMaterializer(entries, context, entityTrackingAdapter, qc, materializerType, null, format); }
/// <summary> /// Initializes a new instance of the <see cref="ODataLoadNavigationPropertyMaterializer" /> class. /// </summary> /// <param name="odataMessageReader">The odata message reader.</param> /// <param name="reader">The reader.</param> /// <param name="materializerContext">The materializer context.</param> /// <param name="entityTrackingAdapter">The entity tracking adapter.</param> /// <param name="queryComponents">The query components.</param> /// <param name="expectedType">The expected type.</param> /// <param name="materializeEntryPlan">The materialize entry plan.</param> /// <param name="responseInfo">LoadProperty Response Info object.</param> public ODataLoadNavigationPropertyMaterializer( ODataMessageReader odataMessageReader, ODataReaderWrapper reader, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan, LoadPropertyResponseInfo responseInfo) : base(odataMessageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, expectedType, materializeEntryPlan) { this.responseInfo = responseInfo; this.items = new List<object>(); }
internal static MaterializeAtom Materialize( ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, string contentType, IODataResponseMessage message, ODataPayloadKind expectedPayloadKind) { Debug.Assert(null != queryComponents, "querycomponents"); Debug.Assert(null != message, "message"); // If there is no content (For e.g. /Customers(1)/BestFriend is null), we need to return empty results. if (message.StatusCode == (int)HttpStatusCode.NoContent || String.IsNullOrEmpty(contentType)) { return(MaterializeAtom.EmptyResults); } return(new MaterializeAtom(responseInfo, queryComponents, plan, message, expectedPayloadKind)); }
#pragma warning restore 649 #endif #endregion Private fields /// <summary> /// constructor /// </summary> /// <param name="responseInfo">originating context</param> /// <param name="queryComponents">Query components (projection, expected type)</param> /// <param name="plan">Projection plan (if compiled in an earlier query).</param> /// <param name="responseMessage">responseMessage</param> /// <param name="payloadKind">The kind of the payload to materialize.</param> internal MaterializeAtom( ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind) { Debug.Assert(queryComponents != null, "queryComponents != null"); this.responseInfo = responseInfo; this.elementType = queryComponents.LastSegmentType; this.expectingPrimitiveValue = PrimitiveType.IsKnownNullableType(elementType); Debug.Assert(responseMessage != null, "Response message is null! Did you mean to use Materializer.ResultsWrapper/EmptyResults?"); Type implementationType; Type materializerType = GetTypeForMaterializer(this.expectingPrimitiveValue, this.elementType, responseInfo.Model, out implementationType); this.materializer = ODataMaterializer.CreateMaterializerForMessage(responseMessage, responseInfo, materializerType, queryComponents, plan, payloadKind); }
/// <summary> /// Get the materializer to process the response. /// </summary> /// <param name="entityDescriptor">entity descriptor whose response is getting materialized.</param> /// <param name="responseInfo">information about the response to be materialized.</param> /// <returns>an instance of MaterializeAtom, that can be used to materialize the response.</returns> /// <remarks> /// This can only be called from inside the HandleBatchResponse or during enumeration of the responses. /// This is used when processing responses for update operations. /// </remarks> protected override MaterializeAtom GetMaterializer(EntityDescriptor entityDescriptor, ResponseInfo responseInfo) { // check if the batch stream is empty or not Debug.Assert(this.currentOperationResponse != null, "There must be an active operation response for this method to work correctly."); Debug.Assert(!this.currentOperationResponse.HasEmptyContent, "We should not get here if the response is empty."); // Since this is used for processing responses to update operations there are no projections to apply. QueryComponents queryComponents = new QueryComponents( /*uri*/ null, Util.ODataVersionEmpty, entityDescriptor.Entity.GetType(), /*projection*/ null, /*normalizerRewrites*/ null); return(new MaterializeAtom( responseInfo, queryComponents, /*projectionPlan*/ null, this.currentOperationResponse.CreateResponseMessage(), ODataPayloadKind.Resource)); }
/// <summary> /// Creates an instance of <see cref="MaterializeAtom"/> for the given plan. /// </summary> /// <param name="plan">The projection plan.</param> /// <param name="payloadKind">expected payload kind.</param> /// <returns>A new materializer instance</returns> private MaterializeAtom CreateMaterializer(ProjectionPlan plan, ODataPayloadKind payloadKind) { QueryComponents queryComponents = this.ServiceRequest.QueryComponents(this.responseInfo.Model); // In V2, in projection path, we did not check for assignability between the expected type and the type returned by the type resolver. if (plan != null || queryComponents.Projection != null) { this.RequestInfo.TypeResolver.IsProjectionRequest(); } var responseMessageWrapper = new HttpWebResponseMessage( new HeaderCollection(this.responseMessage), this.responseMessage.StatusCode, this.GetResponseStream); return(DataServiceRequest.Materialize( this.responseInfo, queryComponents, plan, this.ContentType, responseMessageWrapper, payloadKind)); }
private void MaterializeTest(HttpStatusCode statusCode, ODataPayloadKind payloadKind) { var uri = new Uri("http://any"); var context = new DataServiceContext(); var requestInfo = new RequestInfo(context); var responseInfo = new ResponseInfo(requestInfo, MergeOption.OverwriteChanges); var queryComponents = new QueryComponents(uri, new Version(4, 0), typeof(Product), null, null); var responseMessage = new HttpWebResponseMessage( new HeaderCollection(), (int)statusCode, () => new MemoryStream()); var materialize = DataServiceRequest.Materialize( responseInfo, queryComponents, null, "application/json", responseMessage, payloadKind); Assert.IsNull(materialize.Context); Assert.IsNull(materialize.Current); var enumerable = materialize.Cast<object>(); Assert.AreEqual(0, enumerable.Count()); }
/// <summary> /// Sets the value of the Accept header for a query. /// </summary> /// <param name="headers">The headers to modify.</param> /// <param name="components">The query components for the request.</param> internal void SetRequestAcceptHeaderForQuery(HeaderCollection headers, QueryComponents components) { this.SetAcceptHeaderAndCharset(headers, ChooseMediaType(components.HasSelectQueryOption)); }
/// <summary> /// Synchronizely get the query set count from the server by executing the $count=value query /// </summary> /// <param name="context">The context</param> /// <returns>The server side count of the query set</returns> internal long GetQuerySetCount(DataServiceContext context) { Debug.Assert(null != context, "context is null"); Version requestVersion = this.QueryComponents(context.Model).Version; if (requestVersion == null) { requestVersion = Util.ODataVersion4; } QueryResult response = null; QueryComponents qc = this.QueryComponents(context.Model); Uri requestUri = qc.Uri; DataServiceRequest <long> serviceRequest = new DataServiceRequest <long>(requestUri, qc, null); HeaderCollection headers = new HeaderCollection(); // Validate and set the request DSV header headers.SetRequestVersion(requestVersion, context.MaxProtocolVersionAsVersion); context.Format.SetRequestAcceptHeaderForCount(headers); string httpMethod = XmlConstants.HttpMethodGet; ODataRequestMessageWrapper request = context.CreateODataRequestMessage( context.CreateRequestArgsAndFireBuildingRequest(httpMethod, requestUri, headers, context.HttpStack, null /*descriptor*/), null /*descriptor*/); response = new QueryResult(this, Util.ExecuteMethodName, serviceRequest, request, new RequestInfo(context), null, null); try { response.ExecuteQuery(); if (HttpStatusCode.NoContent != response.StatusCode) { StreamReader sr = new StreamReader(response.GetResponseStream()); long r = -1; try { r = XmlConvert.ToInt64(sr.ReadToEnd()); } finally { sr.Close(); } return(r); } else { throw new DataServiceQueryException(Strings.DataServiceRequest_FailGetCount, response.Failure); } } catch (InvalidOperationException ex) { QueryOperationResponse operationResponse = null; operationResponse = response.GetResponse <long>(MaterializeAtom.EmptyResults); if (null != operationResponse) { operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } throw; } }
/// <summary> /// execute uri and materialize result /// </summary> /// <typeparam name="TElement">element type</typeparam> /// <param name="context">context</param> /// <param name="queryComponents">query components for request to execute</param> /// <returns>enumerable of results</returns> internal QueryOperationResponse <TElement> Execute <TElement>(DataServiceContext context, QueryComponents queryComponents) { QueryResult result = null; try { Uri requestUri = queryComponents.Uri; DataServiceRequest <TElement> serviceRequest = new DataServiceRequest <TElement>(requestUri, queryComponents, this.Plan); result = serviceRequest.CreateExecuteResult(this, context, null, null, Util.ExecuteMethodName); result.ExecuteQuery(); return(result.ProcessResult <TElement>(this.Plan)); } catch (InvalidOperationException ex) { if (result != null) { QueryOperationResponse operationResponse = result.GetResponse <TElement>(MaterializeAtom.EmptyResults); if (null != operationResponse) { if (context.IgnoreResourceNotFoundException) { DataServiceClientException cex = ex as DataServiceClientException; if (cex != null && cex.StatusCode == (int)HttpStatusCode.NotFound) { // don't throw return((QueryOperationResponse <TElement>)operationResponse); } } operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } } throw; } }
public static ODataMaterializer CreateMaterializerForMessage( IODataResponseMessage responseMessage, ResponseInfo responseInfo, Type materializerType, QueryComponents queryComponents, ProjectionPlan plan, ODataPayloadKind payloadKind) { ODataMessageReader messageReader = CreateODataMessageReader(responseMessage, responseInfo, ref payloadKind); ODataMaterializer result; IEdmType edmType = null; try { ODataMaterializerContext materializerContext = new ODataMaterializerContext(responseInfo); // Since in V1/V2, astoria client allowed Execute<object> and depended on the typeresolver or the wire type name // to get the clr type to materialize. Hence if we see the materializer type as object, we should set the edmtype // to null, since there is no expected type. if (materializerType != typeof(System.Object)) { edmType = responseInfo.TypeResolver.ResolveExpectedTypeForReading(materializerType); } if (payloadKind == ODataPayloadKind.Entry || payloadKind == ODataPayloadKind.Feed) { // In V1/V2, we allowed System.Object type to be allowed to pass to ExecuteQuery. // Hence we need to explicitly check for System.Object to allow this if (edmType != null && edmType.TypeKind != EdmTypeKind.Entity) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidNonEntityType(materializerType.FullName)); } ODataReaderWrapper reader = ODataReaderWrapper.Create(messageReader, payloadKind, edmType, responseInfo.ResponsePipeline); EntityTrackingAdapter entityTrackingAdapter = new EntityTrackingAdapter(responseInfo.EntityTracker, responseInfo.MergeOption, responseInfo.Model, responseInfo.Context); LoadPropertyResponseInfo loadPropertyResponseInfo = responseInfo as LoadPropertyResponseInfo; if (loadPropertyResponseInfo != null) { result = new ODataLoadNavigationPropertyMaterializer( messageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, materializerType, plan, loadPropertyResponseInfo); } else { result = new ODataReaderEntityMaterializer( messageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, materializerType, plan); } } else { switch (payloadKind) { case ODataPayloadKind.Value: result = new ODataValueMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Collection: result = new ODataCollectionMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Property: case ODataPayloadKind.IndividualProperty: // Top level properties cannot be of entity type. if (edmType != null && edmType.TypeKind == EdmTypeKind.Entity) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidEntityType(materializerType.FullName)); } result = new ODataPropertyMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.EntityReferenceLinks: case ODataPayloadKind.EntityReferenceLink: result = new ODataLinksMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Error: var odataError = messageReader.ReadError(); throw new ODataErrorException(odataError.Message, odataError); default: throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidResponsePayload(XmlConstants.DataWebNamespace)); } } return result; } catch (Exception ex) { if (CommonUtil.IsCatchableExceptionType(ex)) { // Dispose the message reader in all error scenarios. messageReader.Dispose(); } throw; } }
/// <summary> /// Initializes a new <see cref="QueryComponents"/> instance that can /// be used for this continuation. /// </summary> /// <returns>A new initializes <see cref="QueryComponents"/>.</returns> internal QueryComponents CreateQueryComponents() { // DSV needs to be 2.0 since $skiptoken will be on the uri. QueryComponents result = new QueryComponents(this.NextLinkUri, Util.ODataVersionEmpty, this.Plan.LastSegmentType, null, null); return result; }
/// <summary> /// Get the materializer to process the response. /// </summary> /// <param name="entityDescriptor">entity descriptor whose response is getting materialized.</param> /// <param name="responseInfo">information about the response to be materialized.</param> /// <returns>an instance of MaterializeAtom, that can be used to materialize the response.</returns> /// <remarks> /// This can only be called from inside the HandleBatchResponse or during enumeration of the responses. /// This is used when processing responses for update operations. /// </remarks> protected override MaterializeAtom GetMaterializer(EntityDescriptor entityDescriptor, ResponseInfo responseInfo) { // check if the batch stream is empty or not Debug.Assert(this.currentOperationResponse != null, "There must be an active operation response for this method to work correctly."); Debug.Assert(!this.currentOperationResponse.HasEmptyContent, "We should not get here if the response is empty."); // Since this is used for processing responses to update operations there are no projections to apply. QueryComponents queryComponents = new QueryComponents( /*uri*/ null, Util.ODataVersionEmpty, entityDescriptor.Entity.GetType(), /*projection*/ null, /*normalizerRewrites*/ null); return new MaterializeAtom( responseInfo, queryComponents, /*projectionPlan*/ null, this.currentOperationResponse.CreateResponseMessage(), ODataPayloadKind.Entry); }
/// <summary> /// Sets the value of the Accept header for a query. /// </summary> /// <param name="headers">The headers to modify.</param> /// <param name="components">The query components for the request.</param> internal void SetRequestAcceptHeaderForQuery(HeaderCollection headers, QueryComponents components) { this.SetAcceptHeaderAndCharset(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationAtomOrXml, components.HasSelectQueryOption)); }
/// <summary> /// Generate the batch request for all changes to save. /// </summary> /// <returns>Returns the instance of ODataRequestMessage containing all the headers and payload for the batch request.</returns> private ODataRequestMessageWrapper GenerateBatchRequest() { if (this.ChangedEntries.Count == 0 && this.Queries == null) { this.SetCompleted(); return(null); } ODataRequestMessageWrapper batchRequestMessage = this.CreateBatchRequest(); // we need to fire request after the headers have been written, but before we write the payload batchRequestMessage.FireSendingRequest2(null); using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(batchRequestMessage, this.RequestInfo, false /*isParameterPayload*/)) { this.batchWriter = messageWriter.CreateODataBatchWriter(); this.batchWriter.WriteStartBatch(); if (this.Queries != null) { foreach (DataServiceRequest query in this.Queries) { QueryComponents queryComponents = query.QueryComponents(this.RequestInfo.Model); Uri requestUri = this.RequestInfo.BaseUriResolver.GetOrCreateAbsoluteUri(queryComponents.Uri); Debug.Assert(requestUri != null, "request uri is null"); Debug.Assert(requestUri.IsAbsoluteUri, "request uri is not absolute uri"); HeaderCollection headers = new HeaderCollection(); headers.SetRequestVersion(queryComponents.Version, this.RequestInfo.MaxProtocolVersionAsVersion); this.RequestInfo.Format.SetRequestAcceptHeaderForQuery(headers, queryComponents); ODataRequestMessageWrapper batchOperationRequestMessage = this.CreateRequestMessage(XmlConstants.HttpMethodGet, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/, null /*contentId*/); batchOperationRequestMessage.FireSendingEventHandlers(null /*descriptor*/); } } else if (0 < this.ChangedEntries.Count) { if (Util.IsBatchWithSingleChangeset(this.Options)) { this.batchWriter.WriteStartChangeset(); } var model = this.RequestInfo.Model; for (int i = 0; i < this.ChangedEntries.Count; ++i) { if (Util.IsBatchWithIndependentOperations(this.Options)) { this.batchWriter.WriteStartChangeset(); } Descriptor descriptor = this.ChangedEntries[i]; if (descriptor.ContentGeneratedForSave) { continue; } EntityDescriptor entityDescriptor = descriptor as EntityDescriptor; if (descriptor.DescriptorKind == DescriptorKind.Entity) { if (entityDescriptor.State == EntityStates.Added) { // We don't support adding MLE/MR in batch mode ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())); if (type.IsMediaLinkEntry || entityDescriptor.IsMediaLinkEntry) { throw Error.NotSupported(Strings.Context_BatchNotSupportedForMediaLink); } } else if (entityDescriptor.State == EntityStates.Unchanged || entityDescriptor.State == EntityStates.Modified) { // We don't support PUT for the MR in batch mode // It's OK to PUT the MLE alone inside a batch mode though if (entityDescriptor.SaveStream != null) { throw Error.NotSupported(Strings.Context_BatchNotSupportedForMediaLink); } } } else if (descriptor.DescriptorKind == DescriptorKind.NamedStream) { // Similar to MR, we do not support adding named streams in batch mode. throw Error.NotSupported(Strings.Context_BatchNotSupportedForNamedStreams); } ODataRequestMessageWrapper operationRequestMessage; if (descriptor.DescriptorKind == DescriptorKind.Entity) { operationRequestMessage = this.CreateRequest(entityDescriptor); } else { operationRequestMessage = this.CreateRequest((LinkDescriptor)descriptor); } // we need to fire request after the headers have been written, but before we write the payload operationRequestMessage.FireSendingRequest2(descriptor); this.CreateChangeData(i, operationRequestMessage); if (Util.IsBatchWithIndependentOperations(this.Options)) { this.batchWriter.WriteEndChangeset(); } } if (Util.IsBatchWithSingleChangeset(this.Options)) { this.batchWriter.WriteEndChangeset(); } } this.batchWriter.WriteEndBatch(); this.batchWriter.Flush(); } Debug.Assert(this.ChangedEntries.All(o => o.ContentGeneratedForSave), "didn't generated content for all entities/links"); return(batchRequestMessage); }