/// <summary> /// Reads feed from stream /// </summary> /// <param name="readStream"></param> /// <param name="edmModel"></param> /// <param name="entitySet"></param> /// <param name="expectedBaseEntityType"></param> protected void ReadFeed(Stream readStream, IEdmModel edmModel, IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { readStream.Seek(0, SeekOrigin.Begin); using (var messageReader = ODataMessageHelper.CreateMessageReader(readStream, edmModel)) { ODataReader feedReader = messageReader.CreateODataFeedReader(entitySet, expectedBaseEntityType); while (feedReader.Read()) { } } }
/// <summary> /// Initializes a new instance of the <see cref="EntitySetPathSegment" /> class. /// </summary> /// <param name="entitySet">The entity set being accessed.</param> public EntitySetPathSegment(IEdmEntitySetBase entitySet) { if (entitySet == null) { throw Error.ArgumentNull("entitySet"); } EntitySetBase = entitySet; EntitySetName = entitySet.Name; }
/// <summary> /// Writes an OData Feed with number <see cref="numberOfEntries"/> of entries <see cref="entry"/> /// </summary> /// <param name="writeStream"></param> /// <param name="edmModel"></param> /// <param name="numberOfEntries"></param> /// <param name="entry"></param> /// <param name="entitySet"></param> /// <returns>The payload size</returns> protected Int64 WriteFeed(Stream writeStream, IEdmModel edmModel, long numberOfEntries, ODataEntry entry, IEdmEntitySetBase entitySet) { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(writeStream, edmModel)) { ODataWriter writer = messageWriter.CreateODataFeedWriter(entitySet); writer.WriteStart(new ODataFeed { Id = new Uri("http://www.odata.org/Perf.svc") }); for (long i = 0; i < numberOfEntries; ++i) { writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); writer.Flush(); } return writeStream.Length; // return payload size }
/// <summary> /// Build a segment representing a call to an operation - action, function, or service operation. /// </summary> /// <param name="operation">A single operation import that this segment will represent.</param> /// <param name="entitySet">The <see cref="IEdmEntitySetBase"/> containing the entities that this function returns.</param> /// <exception cref="System.ArgumentNullException">Throws if the input operation is null.</exception> public OperationSegment(IEdmOperation operation, IEdmEntitySetBase entitySet) : this() { ExceptionUtils.CheckArgumentNotNull(operation, "operation"); this.operations = new ReadOnlyCollection <IEdmOperation>(new[] { operation }); this.entitySet = entitySet; this.computedReturnEdmType = operation.ReturnType != null ? operation.ReturnType.Definition : null; this.EnsureTypeAndSetAreCompatable(); if (this.computedReturnEdmType != null) { this.TargetEdmNavigationSource = entitySet; this.TargetEdmType = computedReturnEdmType; this.TargetKind = this.TargetEdmType.GetTargetKindFromType(); this.SingleResult = computedReturnEdmType.TypeKind != EdmTypeKind.Collection; } else { this.TargetEdmNavigationSource = null; this.TargetEdmType = null; this.TargetKind = RequestTargetKind.VoidOperation; } }
/// <summary> /// Writes an OData feed. /// </summary> /// <param name="writer">The ODataWriter that will write the feed.</param> /// <param name="entries">The items from the data store to write to the feed.</param> /// <param name="entitySet">The entity set in the model that the feed belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="selectExpandClause">The SelectExpandClause.</param> public static void WriteFeed(ODataWriter writer, IEnumerable entries, IEdmEntitySetBase entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, long?count, Uri deltaLink, Uri nextPageLink, Dictionary <string, string> incomingHeaders = null) { var feed = new ODataFeed { Id = new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name), DeltaLink = deltaLink, NextPageLink = nextPageLink }; if (count.HasValue) { feed.Count = count; } writer.WriteStart(feed); foreach (var element in entries) { WriteEntry(writer, element, entitySet, targetVersion, selectExpandClause, incomingHeaders); } writer.WriteEnd(); }
private static string GetWriterOutput(ODataResource entry, EdmModel model, IEdmEntitySetBase entitySet, EdmEntityType entityType, IServiceProvider container) { var outputStream = new MemoryStream(); IODataResponseMessage message = new InMemoryMessage { Stream = outputStream, Container = container }; message.SetHeader("Content-Type", "application/json"); var settings = new ODataMessageWriterSettings(); settings.SetServiceDocumentUri(new Uri("http://test")); using (var messageWriter = new ODataMessageWriter(message, settings, model)) { var writer = messageWriter.CreateODataResourceWriter(entitySet, entityType); writer.WriteStart(entry); writer.WriteEnd(); outputStream.Seek(0, SeekOrigin.Begin); return(new StreamReader(outputStream).ReadToEnd()); } }
/// <inheritdoc /> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase; IEdmTypeReference resourceSetType = writeContext.GetEdmType(graph, type); Contract.Assert(resourceSetType != null); IEdmStructuredTypeReference resourceType = GetResourceType(resourceSetType); ODataWriter writer = messageWriter.CreateODataResourceSetWriter(entitySet, resourceType.StructuredDefinition()); WriteObjectInline(graph, resourceSetType, writer, writeContext); }
private static List <MemberExpression> GetKeyExpressions(IEdmEntitySetBase entitySet, OePropertyAccessor[] accessors) { var propertyExpressions = new List <MemberExpression>(); foreach (IEdmStructuralProperty key in entitySet.EntityType().Key()) { bool found = false; foreach (OePropertyAccessor accessor in accessors) { if (String.CompareOrdinal(accessor.EdmProperty.Name, key.Name) == 0) { propertyExpressions.Add(accessor.PropertyExpression); found = true; break; } } if (!found) { throw new InvalidOperationException("Key property " + key.Name + " not found in accessors"); } } return(propertyExpressions); }
/// <summary> /// Writes the entity collection results to the response message. /// </summary> /// <param name="graph">The entity collection results.</param> /// <param name="type">The type of the entities.</param> /// <param name="messageWriter">The message writer.</param> /// <param name="writeContext">The writing context.</param> public override void WriteObject( object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { Ensure.NotNull(messageWriter, "messageWriter"); Ensure.NotNull(writeContext, "writeContext"); IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase; if (entitySet == null) { throw new SerializationException(Resources.EntitySetMissingForSerialization); } EntityCollectionResult collectionResult = (EntityCollectionResult)graph; IEdmTypeReference feedType = collectionResult.EdmType; IEdmEntityTypeReference entityType = GetEntityType(feedType); ODataWriter writer = messageWriter.CreateODataFeedWriter(entitySet, entityType.EntityDefinition()); this.WriteObjectInline(collectionResult.Query, feedType, writer, writeContext); }
public BatchReferenceSegment(string contentId, IEdmType edmType, IEdmEntitySetBase entitySet) { ExceptionUtils.CheckArgumentNotNull(edmType, "resultingType"); ExceptionUtils.CheckArgumentNotNull(contentId, "contentId"); if (!ODataPathParser.ContentIdRegex.IsMatch(contentId)) { throw new ODataException(ODataErrorStrings.BatchReferenceSegment_InvalidContentID(contentId)); } this.edmType = edmType; this.entitySet = entitySet; this.contentId = contentId; this.Identifier = this.ContentId; this.TargetEdmType = edmType; this.TargetEdmNavigationSource = this.EntitySet; this.SingleResult = true; this.TargetKind = RequestTargetKind.Resource; if (entitySet != null) { UriParserErrorHelper.ThrowIfTypesUnrelated(edmType, entitySet.EntityType(), "BatchReferenceSegments"); } }
/// <summary> /// Creates an EntityCollectionFunctionCallNode to represent a operation call that returns a collection of entities. /// </summary> /// <param name="name">The name of this operation.</param> /// <param name="functions">the list of functions that this node should represent.</param> /// <param name="parameters">the list of parameters to this operation</param> /// <param name="returnedCollectionTypeReference">the type the entity collection returned by this operation. The element type must be an entity type.</param> /// <param name="navigationSource">the set containing entities returned by this operation</param> /// <param name="source">the semantically bound parent of this EntityCollectionFunctionCallNode.</param> /// <exception cref="System.ArgumentNullException">Throws if the provided name is null.</exception> /// <exception cref="System.ArgumentNullException">Throws if the provided collection type reference is null.</exception> /// <exception cref="System.ArgumentException">Throws if the element type of the provided collection type reference is not an entity type.</exception> /// <exception cref="System.ArgumentNullException">Throws if the input operation imports is null</exception> public EntityCollectionFunctionCallNode(string name, IEnumerable <IEdmFunction> functions, IEnumerable <QueryNode> parameters, IEdmCollectionTypeReference returnedCollectionTypeReference, IEdmEntitySetBase navigationSource, QueryNode source) { ExceptionUtils.CheckArgumentNotNull(name, "name"); ExceptionUtils.CheckArgumentNotNull(returnedCollectionTypeReference, "returnedCollectionTypeReference"); this.name = name; this.functions = new ReadOnlyCollection <IEdmFunction>(functions == null ? new List <IEdmFunction>() : functions.ToList()); this.parameters = new ReadOnlyCollection <QueryNode>(parameters == null ? new List <QueryNode>() : parameters.ToList()); this.returnedCollectionTypeReference = returnedCollectionTypeReference; this.navigationSource = navigationSource; this.entityTypeReference = returnedCollectionTypeReference.ElementType().AsEntityOrNull(); if (this.entityTypeReference == null) { throw new ArgumentException(ODataErrorStrings.Nodes_EntityCollectionFunctionCallNode_ItemTypeMustBeAnEntity); } this.source = source; }
/// <summary> /// Creates a segment representing a call to an operation - action, function or service operation. /// </summary> /// <param name="operationImports">The list of possible FunctionImport overloads for this segment.</param> /// <param name="entitySet">The <see cref="IEdmEntitySetBase"/> containing the entities that this function returns.</param> /// <param name="parameters">The list of parameters supplied to this segment.</param> public OperationImportSegment(IEnumerable <IEdmOperationImport> operationImports, IEdmEntitySetBase entitySet, IEnumerable <OperationSegmentParameter> parameters) : this(operationImports, entitySet) { this.parameters = new ReadOnlyCollection <OperationSegmentParameter>(parameters == null ? new List <OperationSegmentParameter>() : parameters.ToList()); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> public override ODataReader CreateFeedReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { this.AssertSynchronous(); return this.CreateFeedReaderImplementation(entitySet, expectedBaseEntityType); }
private object ProcessPostBody(IODataRequestMessage message, IEdmEntitySetBase entitySet, object queryResults) { object lastNewInstance = null; using (var messageReader = new ODataMessageReader(message, this.GetReaderSettings(), this.DataSource.Model)) { var odataItemStack = new Stack<ODataItem>(); var entryReader = messageReader.CreateODataEntryReader(entitySet, entitySet.EntityType()); var currentTargetEntitySet = entitySet; while (entryReader.Read()) { switch (entryReader.State) { case ODataReaderState.EntryStart: odataItemStack.Push(entryReader.Item); break; case ODataReaderState.EntryEnd: { var entry = (ODataEntry)entryReader.Item; // TODO: the code here will be changed to handle following scenarios // 1: non-contained navigation, e.g. People(1)/Friends // 2. general entity set, e.g. People // 3. contained navigation, e.g. People(1)/Trips // 4. upsert, e.g. People(1)/Friends(2) var newInstance = this.DataSource.UpdateProvider.Create(entry.TypeName, queryResults); foreach (var property in entry.Properties) { if (Utility.IsETagProperty(newInstance, property.Name)) continue; this.DataSource.UpdateProvider.Update(newInstance, property.Name, property.Value); } var boundNavPropAnnotation = odataItemStack.Pop().GetAnnotation<BoundNavigationPropertyAnnotation>(); if (boundNavPropAnnotation != null) { foreach (var boundProperty in boundNavPropAnnotation.BoundProperties) { var isCollection = boundProperty.Item1.IsCollection == true; var propertyValue = isCollection ? boundProperty.Item2 : ((IEnumerable<object>)boundProperty.Item2).Single(); this.DataSource.UpdateProvider.Update(newInstance, boundProperty.Item1.Name, propertyValue); } } var parentItem = odataItemStack.Count > 0 ? odataItemStack.Peek() : null; if (parentItem != null) { // This new entry belongs to a navigation property and/or feed - // propagate it up the tree for further processing. AddChildInstanceAnnotation(parentItem, newInstance); } lastNewInstance = newInstance; } break; case ODataReaderState.FeedStart: odataItemStack.Push(entryReader.Item); break; case ODataReaderState.FeedEnd: { var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>(); var parentNavLink = odataItemStack.Count > 0 ? odataItemStack.Peek() as ODataNavigationLink : null; if (parentNavLink != null) { // This feed belongs to a navigation property - // propagate it up the tree for further processing. AddChildInstanceAnnotation(parentNavLink, childAnnotation.ChildInstances ?? new object[0]); } } break; case ODataReaderState.NavigationLinkStart: { odataItemStack.Push(entryReader.Item); var navigationLink = (ODataNavigationLink)entryReader.Item; var navigationProperty = (IEdmNavigationProperty)currentTargetEntitySet.EntityType().FindProperty(navigationLink.Name); // Current model implementation doesn't expose associations otherwise this would be much cleaner. currentTargetEntitySet = this.DataSource.Model.EntityContainer.EntitySets().Single(s => s.EntityType() == navigationProperty.Type.Definition); } break; case ODataReaderState.NavigationLinkEnd: { var navigationLink = (ODataNavigationLink)entryReader.Item; var childAnnotation = odataItemStack.Pop().GetAnnotation<ChildInstanceAnnotation>(); if (childAnnotation != null) { // Propagate the bound entries to the parent entry. AddBoundNavigationPropertyAnnotation(odataItemStack.Peek(), navigationLink, childAnnotation.ChildInstances); } } break; } } } return lastNewInstance; }
/// <summary> /// Asynchronously creates an <see cref="ODataDeltaReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataDeltaReader"/>.</returns> internal virtual Task <ODataDeltaReader> CreateDeltaReaderAsync(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
private async Task WriteResourceSet(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(resourceSetType != null); IEdmStructuredTypeReference elementType = GetResourceType(resourceSetType); ODataResourceSet resourceSet = CreateResourceSet(enumerable, resourceSetType.AsCollection(), writeContext); if (resourceSet == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, ResourceSet)); } IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase; if (entitySet == null) { resourceSet.SetSerializationInfo(new ODataResourceSerializationInfo { IsFromCollection = true, NavigationSourceEntityTypeName = elementType.FullName(), NavigationSourceKind = EdmNavigationSourceKind.UnknownEntitySet, NavigationSourceName = null }); } ODataEdmTypeSerializer resourceSerializer = SerializerProvider.GetEdmTypeSerializer(writeContext.Context, elementType); if (resourceSerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataOutputFormatter).Name)); } // save this for later to support JSON odata.streaming. Uri nextPageLink = resourceSet.NextPageLink; resourceSet.CountOnly = enumerable is ICountOptionCollection && (enumerable as ITruncatedCollection).OnlyCount; resourceSet.NextPageLink = null; writer.WriteStart(resourceSet); foreach (object item in enumerable) { if (item == null || item is NullEdmComplexObject) { if (elementType.IsEntity()) { throw new SerializationException(SRResources.NullElementInCollection); } // for null complex element, it can be serialized as "null" in the collection. writer.WriteStart(resource: null); writer.WriteEnd(); } else { await resourceSerializer.WriteObjectInlineAsync(item, elementType, writer, writeContext); } } // Subtle and surprising behavior: If the NextPageLink property is set before calling WriteStart(resourceSet), // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if // the next page link is not set when calling WriteStart(resourceSet) but is instead set later on that resourceSet // object before calling WriteEnd(), the next page link will be written at the end, as required for // odata.streaming=true support. if (nextPageLink != null) { resourceSet.NextPageLink = nextPageLink; } writer.WriteEnd(); }
/// <summary> /// Asynchronously creates an <see cref="ODataDeltaWriter" /> to write a delta response. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the resource set to be written (or null if the entity set base type should be used).</param> /// <returns>A running task for the created writer.</returns> /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks> internal override Task <ODataDeltaWriter> CreateODataDeltaWriterAsync(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { this.AssertAsynchronous(); return(TaskUtils.GetTaskForSynchronousOperation(() => this.CreateODataDeltaWriterImplementation(entitySet, entityType))); }
/// <summary> /// Creates an <see cref="ODataDeltaReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>The newly created <see cref="ODataDeltaReader"/>.</returns> internal virtual ODataDeltaReader CreateDeltaReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
private string GetWriterOutputForContentTypeAndKnobValue(ODataEntry entry, EdmModel model, IEdmEntitySetBase entitySet, EdmEntityType entityType) { MemoryStream outputStream = new MemoryStream(); IODataResponseMessage message = new InMemoryMessage() { Stream = outputStream }; message.SetHeader("Content-Type", "application/json;odata.metadata=full"); ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { AutoComputePayloadMetadataInJson = true, }; settings.SetServiceDocumentUri(new Uri("http://example.com")); string output; using (var messageWriter = new ODataMessageWriter(message, settings, model)) { ODataWriter writer = messageWriter.CreateODataEntryWriter(entitySet, entityType); writer.WriteStart(entry); writer.WriteEnd(); outputStream.Seek(0, SeekOrigin.Begin); output = new StreamReader(outputStream).ReadToEnd(); } return output; }
public override ODataReader CreateFeedReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return new ODataAvroReader(this, true); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateFeedReaderImplementation(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return new ODataAtomReader(this, entitySet, expectedBaseEntityType, true); }
/// <summary> /// Creates an <see cref="ODataDeltaReader" /> to read a resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataDeltaReader CreateDeltaReaderImplementation(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return(new ODataJsonLightDeltaReader(this, entitySet, expectedBaseEntityType)); }
/// <summary> /// Gets the target entity set for the given operation import. /// </summary> /// <param name="operationImport">The operation import.</param> /// <param name="sourceEntitySet">The source entity set.</param> /// <param name="model">The model.</param> /// <returns>The target entity set of the operation import or null if it could not be determined.</returns> internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperationImport operationImport, IEdmEntitySetBase sourceEntitySet, IEdmModel model) { IEdmEntitySet targetEntitySet; if (operationImport.TryGetStaticEntitySet(out targetEntitySet)) { return(targetEntitySet); } if (sourceEntitySet == null) { return(null); } if (operationImport.Operation.IsBound && operationImport.Operation.Parameters.Any()) { IEdmOperationParameter parameter; IEnumerable <IEdmNavigationProperty> path; IEnumerable <EdmError> errors; if (operationImport.TryGetRelativeEntitySetPath(model, out parameter, out path, out errors)) { IEdmEntitySetBase currentEntitySet = sourceEntitySet; foreach (var navigation in path) { currentEntitySet = currentEntitySet.FindNavigationTarget(navigation) as IEdmEntitySetBase; if (currentEntitySet == null || currentEntitySet is IEdmUnknownEntitySet) { return(currentEntitySet); } } return(currentEntitySet); } else { bool foundSyntaxError = !errors.Any(e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName); ExceptionUtil.ThrowSyntaxErrorIfNotValid(foundSyntaxError); } } return(null); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a resource set in a Uri operation parameter. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public virtual Task <ODataReader> CreateUriParameterResourceSetReaderAsync(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.ResourceSet); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> internal override ODataReader CreateFeedReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { this.AssertSynchronous(); return(this.CreateFeedReaderImplementation(entitySet, expectedBaseEntityType)); }
public static ResourceRangeVariableReferenceNode CreateRangeVariableReferenceNode(IEdmEntitySetBase entitySet, String name = null) { var entityTypeRef = (IEdmEntityTypeReference)((IEdmCollectionType)entitySet.Type).ElementType; var rangeVariable = new ResourceRangeVariable(name ?? "$it", entityTypeRef, entitySet); return(new ResourceRangeVariableReferenceNode(name ?? "$it", rangeVariable)); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateFeedReaderImplementation(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return(new ODataJsonLightReader(this, entitySet, expectedBaseEntityType, true, null /*listener*/)); }
/// <summary> /// Asynchronously creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the feed.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataReader"/>.</returns> public virtual Task<ODataReader> CreateFeedReaderAsync(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
private string GetWriterOutputForContentTypeAndKnobValue( string contentType, bool autoComputePayloadMetadataInJson, ODataItem[] itemsToWrite, EdmModel edmModel, IEdmEntitySetBase edmEntitySet, EdmEntityType edmEntityType, string selectClause = null, string expandClause = null, string resourcePath = null, bool enableFullValidation = true) { MemoryStream outputStream = new MemoryStream(); IODataResponseMessage message = new InMemoryMessage() { Stream = outputStream }; message.SetHeader("Content-Type", contentType); ODataMessageWriterSettings settings = new ODataMessageWriterSettings() { AutoComputePayloadMetadataInJson = autoComputePayloadMetadataInJson, EnableFullValidation = enableFullValidation }; var result = new ODataQueryOptionParser(edmModel, edmEntityType, edmEntitySet, new Dictionary<string, string> { { "$expand", expandClause }, { "$select", selectClause } }).ParseSelectAndExpand(); ODataUri odataUri = new ODataUri() { ServiceRoot = new Uri("http://example.org/odata.svc"), SelectAndExpand = result }; if (resourcePath != null) { Uri requestUri = new Uri("http://example.org/odata.svc/" + resourcePath); odataUri.RequestUri = requestUri; odataUri.Path = new ODataUriParser(edmModel, new Uri("http://example.org/odata.svc/"), requestUri).ParsePath(); } settings.ODataUri = odataUri; string output; using (var messageWriter = new ODataMessageWriter(message, settings, edmModel)) { int currentIdx = 0; if (itemsToWrite[currentIdx] is ODataFeed) { ODataWriter writer = messageWriter.CreateODataFeedWriter(edmEntitySet, edmEntityType); this.WriteFeed(writer, itemsToWrite, ref currentIdx); } else if (itemsToWrite[currentIdx] is ODataEntry) { ODataWriter writer = messageWriter.CreateODataEntryWriter(edmEntitySet, edmEntityType); this.WriteEntry(writer, itemsToWrite, ref currentIdx); } else { Assert.True(false, "Top level item to write must be entry or feed."); } currentIdx.Should().Be(itemsToWrite.Length, "Invalid list of items to write."); outputStream.Seek(0, SeekOrigin.Begin); output = new StreamReader(outputStream).ReadToEnd(); } return output; }
private static KeySegment BuildKeySegment(IEdmEntityType entityType, IEdmEntitySetBase entitySet, object target) { if (entityType == null) { throw new ArgumentNullException("entityType"); } if (entitySet == null) { throw new ArgumentNullException("entitySet"); } if (target == null) { throw new ArgumentNullException("target"); } KeySegment keySegment = new KeySegment( entityType.Key().Select( (key) => { var keyValue = target.GetType().GetProperty(key.Name).GetValue(target, null); return new KeyValuePair<string, object>(key.Name, keyValue); }), entityType, entitySet); return keySegment; }
/// <summary> /// Writes an OData feed. /// </summary> /// <param name="writer">The ODataWriter that will write the feed.</param> /// <param name="entityType">The type of the entity in the feed.</param> /// <param name="entries">The items from the data store to write to the feed.</param> /// <param name="entitySet">The entity set in the model that the feed belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="selectExpandClause">The SelectExpandClause.</param> public static void WriteFeed(ODataWriter writer, IEdmEntityType entityType, IEnumerable entries, IEdmEntitySetBase entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, long? count, Uri deltaLink, Uri nextPageLink, Dictionary<string, string> incomingHeaders = null) { var feed = new ODataFeed { Id = entitySet == null ? null : new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name), DeltaLink = deltaLink, NextPageLink = nextPageLink }; if (entitySet == null) { feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = entityType.FullTypeName(), NavigationSourceName = null, NavigationSourceKind = EdmNavigationSourceKind.UnknownEntitySet, IsFromCollection = true }); } if (count.HasValue) { feed.Count = count; } writer.WriteStart(feed); foreach (var element in entries) { WriteEntry(writer, element, entitySet, targetVersion, selectExpandClause, incomingHeaders); } writer.WriteEnd(); }
private void WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(feedType != null); IEdmEntityTypeReference elementType = GetEntityType(feedType); ODataFeed feed = CreateODataFeed(enumerable, feedType.AsCollection(), writeContext); if (feed == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, Feed)); } IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase; if (entitySet == null) { feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { IsFromCollection = true, NavigationSourceEntityTypeName = elementType.FullName(), NavigationSourceKind = EdmNavigationSourceKind.UnknownEntitySet, NavigationSourceName = null }); } ODataEdmTypeSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType); if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataMediaTypeFormatter).Name)); } // save this for later to support JSON odata.streaming. Uri nextPageLink = feed.NextPageLink; feed.NextPageLink = null; writer.WriteStart(feed); foreach (object entry in enumerable) { if (entry == null) { throw new SerializationException(SRResources.NullElementInCollection); } entrySerializer.WriteObjectInline(entry, elementType, writer, writeContext); } // Subtle and suprising behavior: If the NextPageLink property is set before calling WriteStart(feed), // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if // the next page link is not set when calling WriteStart(feed) but is instead set later on that feed // object before calling WriteEnd(), the next page link will be written at the end, as required for // odata.streaming=true support. if (nextPageLink != null) { feed.NextPageLink = nextPageLink; } writer.WriteEnd(); }
/// <summary> /// Gets the target entity set for the given operation import. /// </summary> /// <param name="operationImport">The operation import.</param> /// <param name="sourceEntitySet">The source entity set.</param> /// <param name="model">The model.</param> /// <returns>The target entity set of the operation import or null if it could not be determined.</returns> internal static IEdmEntitySetBase GetTargetEntitySet(this IEdmOperationImport operationImport, IEdmEntitySetBase sourceEntitySet, IEdmModel model) { IEdmEntitySet targetEntitySet; if (operationImport.TryGetStaticEntitySet(out targetEntitySet)) { return targetEntitySet; } if (sourceEntitySet == null) { return null; } if (operationImport.Operation.IsBound && operationImport.Operation.Parameters.Any()) { IEdmOperationParameter parameter; IEnumerable<IEdmNavigationProperty> path; IEnumerable<EdmError> errors; if (operationImport.TryGetRelativeEntitySetPath(model, out parameter, out path, out errors)) { IEdmEntitySetBase currentEntitySet = sourceEntitySet; foreach (var navigation in path) { currentEntitySet = currentEntitySet.FindNavigationTarget(navigation) as IEdmEntitySetBase; if (currentEntitySet == null || currentEntitySet is IEdmUnknownEntitySet) { return currentEntitySet; } } return currentEntitySet; } else { if (errors.Any( e => e.ErrorCode == EdmErrorCode.InvalidPathFirstPathParameterNotMatchingFirstParameterName)) { throw ExceptionUtil.CreateSyntaxError(); } } } return null; }
/// <summary> /// Writes an OData Feed with number <see cref="numberOfEntries"/> of entries <see cref="entry"/> /// </summary> /// <param name="writeStream"></param> /// <param name="edmModel"></param> /// <param name="numberOfEntries"></param> /// <param name="entry"></param> /// <param name="entitySet"></param> /// <returns>The payload size</returns> protected Int64 WriteFeed(Stream writeStream, IEdmModel edmModel, long numberOfEntries, ODataEntry entry, IEdmEntitySetBase entitySet) { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(writeStream, edmModel)) { ODataWriter writer = messageWriter.CreateODataFeedWriter(entitySet); writer.WriteStart(new ODataFeed { Id = new Uri("http://www.odata.org/Perf.svc") }); for (long i = 0; i < numberOfEntries; ++i) { writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); writer.Flush(); } return(writeStream.Length); // return payload size }
/// <summary> /// Creates an <see cref="ODataDeltaReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>The newly created <see cref="ODataDeltaReader"/>.</returns> internal override ODataDeltaReader CreateDeltaReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { this.AssertSynchronous(); this.VerifyCanCreateODataReader(entitySet, expectedBaseEntityType); return this.CreateDeltaReaderImplementation(entitySet, expectedBaseEntityType); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateFeedReaderImplementation(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return(new ODataAtomReader(this, entitySet, expectedBaseEntityType, true)); }
/// <summary> /// Asynchronously creates an <see cref="ODataDeltaReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>Task which when completed returns the newly created <see cref="ODataDeltaReader"/>.</returns> internal override Task<ODataDeltaReader> CreateDeltaReaderAsync(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { this.AssertAsynchronous(); this.VerifyCanCreateODataReader(entitySet, expectedBaseEntityType); // Note that the reading is actually synchronous since we buffer the entire input when getting the stream from the message. return TaskUtils.GetTaskForSynchronousOperation(() => this.CreateDeltaReaderImplementation(entitySet, expectedBaseEntityType)); }
/// <summary> /// Creates an <see cref="ODataDeltaReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataDeltaReader CreateDeltaReaderImplementation(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return new ODataJsonLightDeltaReader(this, entitySet, expectedBaseEntityType); }
public override ODataWriter CreateODataFeedWriter(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { return new ODataAvroWriter(this, value => this.AvroWriter.Write(value), this.AvroWriter.UpdateSchema(null, entityType, true), true); }
public static OePropertyAccessor[] CreateFromType(Type clrType, IEdmEntitySetBase entitySet) { ParameterExpression parameter = Expression.Parameter(typeof(Object)); UnaryExpression instance = Expression.Convert(parameter, clrType); var propertyAccessors = new List <OePropertyAccessor>(); foreach (IEdmStructuralProperty edmProperty in entitySet.EntityType().StructuralProperties()) { MemberExpression expression = Expression.Property(instance, clrType.GetProperty(edmProperty.Name)); propertyAccessors.Add(CreatePropertyAccessor(edmProperty, expression, parameter, false)); } return(propertyAccessors.ToArray()); }
/// <summary> /// Writes an OData feed. /// </summary> /// <param name="writer">The ODataWriter that will write the feed.</param> /// <param name="entries">The items from the data store to write to the feed.</param> /// <param name="entitySet">The entity set in the model that the feed belongs to.</param> /// <param name="targetVersion">The OData version this segment is targeting.</param> /// <param name="selectExpandClause">The SelectExpandClause.</param> public static void WriteFeed(ODataWriter writer, IEnumerable entries, IEdmEntitySetBase entitySet, ODataVersion targetVersion, SelectExpandClause selectExpandClause, long? count, Uri deltaLink, Uri nextPageLink, Dictionary<string, string> incomingHeaders = null) { var feed = new ODataFeed { Id = new Uri(ServiceConstants.ServiceBaseUri, entitySet.Name), DeltaLink = deltaLink, NextPageLink = nextPageLink }; if (count.HasValue) { feed.Count = count; } writer.WriteStart(feed); foreach (var element in entries) { WriteEntry(writer, element, entitySet, targetVersion, selectExpandClause, incomingHeaders); } writer.WriteEnd(); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { object result; if (this.HttpMethod == HttpMethod.GET) { // we cannot invoke same action request multiple times, so only Functions are allowed to do the server-driven paging this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext); result = this.ProcessFunction(); if (this.PreferenceContext.MaxPageSize.HasValue) { responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value)); } } else { // TODO: currently ETag feature does not support action operation result = this.ProcessAction(requestMessage); } if (result == null) { // Protocol 9.1.4 Response Code 204 No Content // A request returns 204 No Content if the requested resource has the null value, // or if the service applies a return=minimal preference. In this case, the response body MUST be empty. ResponseWriter.WriteEmptyResponse(responseMessage); return; } using (var messageWriter = this.CreateMessageWriter(responseMessage)) { if (this.QueryContext.Target.TypeKind == EdmTypeKind.None || this.QueryContext.Target.TypeKind == EdmTypeKind.EntityReference || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.EntityReference) { throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported return type in operation.", null); } else if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Entity || this.QueryContext.Target.TypeKind == EdmTypeKind.Complex || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Complex) { ODataWriter resultWriter; IEdmNavigationSource entitySource = this.QueryContext.OperationResultSource ?? this.QueryContext.Target.NavigationSource; if (this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { IEdmEntitySetBase entitySet = (IEdmEntitySetBase)entitySource; resultWriter = messageWriter.CreateODataResourceSetWriter(entitySet, (IEdmStructuredType)this.QueryContext.Target.ElementType); ResponseWriter.WriteFeed(resultWriter, (IEdmStructuredType)this.QueryContext.Target.ElementType, result as IEnumerable, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, null, this.QueryContext.NextLink, this.RequestHeaders); } else { if (this.HttpMethod == HttpMethod.GET) { var currentETag = Utility.GetETagValue(result); // if the current entity has ETag field if (currentETag != null) { string requestETag; if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag)) { ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified); return; } responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag); } } resultWriter = messageWriter.CreateODataResourceWriter(entitySource, (IEdmStructuredType)this.QueryContext.Target.Type); ResponseWriter.WriteEntry(resultWriter, result, entitySource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders); } } else { ODataProperty property = new ODataProperty() { Name = "value", Value = ODataObjectModelConverter.CreateODataValue(result) }; messageWriter.WriteProperty(property); } } }
/// <summary> /// Creates an <see cref="ODataDeltaWriter" /> to write a delta response. /// </summary> /// <returns>The created writer.</returns> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks> internal override ODataDeltaWriter CreateODataDeltaWriter(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { this.AssertSynchronous(); return this.CreateODataDeltaWriterImplementation(entitySet, entityType); }
public OperationImportSegment(IEnumerable <IEdmOperationImport> operationImports, IEdmEntitySetBase entitySet) : this() { // DEVNOTE: This ctor is only used in Select and Expand currently. ExceptionUtils.CheckArgumentNotNull(operationImports, "operations"); this.operationImports = new ReadOnlyCollection <IEdmOperationImport>(operationImports.ToList()); // check for empty after we copy locally, so that we don't do multiple enumeration of input ExceptionUtils.CheckArgumentCollectionNotNullOrEmpty(this.operationImports, "operations"); // Determine the return type of the operation. This is only possible if all the candidate operations agree on the return type. // TODO: Because we work on types and not type references, if there are nullability differences we'd ignore them... IEdmType typeSoFar = this.operationImports.First().Operation.ReturnType != null ? this.operationImports.First().Operation.ReturnType.Definition : null; if (typeSoFar == null) { // This is for void operations if (this.operationImports.Any(operation => operation.Operation.ReturnType != null)) { typeSoFar = UnknownSentinel; } } else if (this.operationImports.Any(operationImport => !typeSoFar.IsEquivalentTo(operationImport.Operation.ReturnType.Definition))) { typeSoFar = UnknownSentinel; } this.computedReturnEdmType = typeSoFar; this.entitySet = entitySet; this.EnsureTypeAndSetAreCompatable(); }
/// <summary> /// Asynchronously creates an <see cref="ODataDeltaWriter" /> to write a delta response. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <returns>A running task for the created writer.</returns> /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks> internal override Task<ODataDeltaWriter> CreateODataDeltaWriterAsync(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { this.AssertAsynchronous(); return TaskUtils.GetTaskForSynchronousOperation(() => this.CreateODataDeltaWriterImplementation(entitySet, entityType)); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <param name="readingParameter">true means reading a resource set in uri operation parameter, false reading a resource set in other payloads.</param> /// <param name="readingDelta">true if reading a delta resource set.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> private ODataReader CreateResourceSetReaderImplementation(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType, bool readingParameter, bool readingDelta) { return(new ODataJsonLightReader(this, entitySet, expectedResourceType, /*readingResourceSet*/ true, readingParameter, readingDelta)); }
//// Raw value is not supported by JsonLight. /// <summary> /// Creates an <see cref="ODataWriter" /> to write a feed. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <returns>The created writer.</returns> private ODataWriter CreateODataFeedWriterImplementation(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { ODataJsonLightWriter odataJsonWriter = new ODataJsonLightWriter(this, entitySet, entityType, /*writingFeed*/true); this.outputInStreamErrorListener = odataJsonWriter; return odataJsonWriter; }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a delta resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read resources for.</param> /// <param name="expectedResourceType">The expected structured type for the items in the resource set.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> public virtual ODataReader CreateDeltaResourceSetReader(IEdmEntitySetBase entitySet, IEdmStructuredType expectedResourceType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.ResourceSet); }
/// <summary> /// Creates an <see cref="ODataDeltaWriter" /> to write a delta response. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <returns>The created writer.</returns> private ODataDeltaWriter CreateODataDeltaWriterImplementation(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { ODataJsonLightDeltaWriter odataJsonDeltaWriter = new ODataJsonLightDeltaWriter(this, entitySet, entityType); this.outputInStreamErrorListener = odataJsonDeltaWriter; return odataJsonDeltaWriter; }
/// <summary> /// Creates an <see cref="ODataDeltaReader" /> to read a resource set. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the delta response.</param> /// <returns>The newly created <see cref="ODataDeltaReader"/>.</returns> internal virtual ODataDeltaReader CreateDeltaReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.ResourceSet); }
/// <summary> /// Creates an <see cref="ODataWriter" /> to write a feed. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <returns>The created writer.</returns> /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks> public virtual ODataWriter CreateODataFeedWriter(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
public override ODataReader CreateFeedReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { return(new ODataAvroReader(this, true)); }
/// <summary> /// Asynchronously creates an <see cref="ODataDeltaWriter" /> to write a delta response. /// </summary> /// <param name="entitySet">The entity set we are going to write entities for.</param> /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param> /// <returns>A running task for the created writer.</returns> /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks> internal virtual Task<ODataDeltaWriter> CreateODataDeltaWriterAsync(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
/// <summary> /// Creates an <see cref="ODataReader" /> to read a feed. /// </summary> /// <param name="entitySet">The entity set we are going to read entities for.</param> /// <param name="expectedBaseEntityType">The expected base entity type for the entries in the feed.</param> /// <returns>The newly created <see cref="ODataReader"/>.</returns> public virtual ODataReader CreateFeedReader(IEdmEntitySetBase entitySet, IEdmEntityType expectedBaseEntityType) { throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Feed); }
/// <summary> /// Determines the entity set for segment. /// </summary> /// <param name="identifier">The identifier.</param> /// <param name="returnType">Type of the return.</param> /// <param name="segment">The segment.</param> /// <param name="targetset">The targetset.</param> /// <param name="singleOperation">The single operation.</param> /// <exception cref="ODataException">Throws and exception if entity set not specified.</exception> private static void DetermineEntitySetForSegment(string identifier, IEdmTypeReference returnType, ODataPathSegment segment, IEdmEntitySetBase targetset, IEdmOperation singleOperation) { if (returnType != null) { segment.TargetEdmNavigationSource = targetset; segment.TargetEdmType = returnType.Definition; segment.TargetKind = TargetKindFromType(segment.TargetEdmType); segment.SingleResult = !singleOperation.ReturnType.IsCollection(); } else { segment.TargetEdmNavigationSource = null; segment.TargetEdmType = null; segment.TargetKind = RequestTargetKind.VoidOperation; } }
/// <summary> /// Try to bind an identifier to a FunctionCallNode /// </summary> /// <param name="identifier">the identifier to bind</param> /// <param name="arguments">the semantically bound list of arguments.</param> /// <param name="parent">a semantically bound parent node.</param> /// <param name="state">the current state of the binding algorithm</param> /// <param name="boundFunction">a single value function call node representing this function call, if we found one.</param> /// <returns>true if we found a function for this token.</returns> private bool TryBindIdentifier(string identifier, IEnumerable <FunctionParameterToken> arguments, QueryNode parent, BindingState state, out QueryNode boundFunction) { boundFunction = null; IEdmType bindingType = null; SingleValueNode singleValueParent = parent as SingleValueNode; if (singleValueParent != null) { if (singleValueParent.TypeReference != null) { bindingType = singleValueParent.TypeReference.Definition; } } else { CollectionNode collectionValueParent = parent as CollectionNode; if (collectionValueParent != null) { bindingType = collectionValueParent.CollectionType.Definition; } } if (!UriEdmHelpers.IsBindingTypeValid(bindingType)) { return(false); } // All functions should be fully qualified, if they aren't they they aren't functions. // When using extension, there may be function call with unqualified name. So loose the restriction here. if (identifier.IndexOf(".", StringComparison.Ordinal) == -1 && this.Resolver.GetType() == typeof(ODataUriResolver)) { return(false); } IEdmOperation operation; List <FunctionParameterToken> syntacticArguments = arguments == null ? new List <FunctionParameterToken>() : arguments.ToList(); if (!FunctionOverloadResolver.ResolveOperationFromList(identifier, syntacticArguments.Select(ar => ar.ParameterName).ToList(), bindingType, state.Model, out operation, this.Resolver)) { // TODO: FunctionOverloadResolver.ResolveOperationFromList() looks up the function by parameter names, but it shouldn't ignore parameter types. (test case ParseFilter_AliasInFunction_PropertyAsValue_TypeMismatch should fail) return(false); } if (singleValueParent != null && singleValueParent.TypeReference == null) { // if the parent exists, but has no type information, then we're in open type land, and we // shouldn't go any farther. throw new ODataException(ODataErrorStrings.FunctionCallBinder_CallingFunctionOnOpenProperty(identifier)); } if (operation.IsAction()) { return(false); } IEdmFunction function = (IEdmFunction)operation; // TODO: $filter $orderby parameter expression which contains complex or collection should NOT be supported in this way // but should be parsed into token tree, and binded to node tree: parsedParameters.Select(p => this.bindMethod(p)); ICollection <FunctionParameterToken> parsedParameters = HandleComplexOrCollectionParameterValueIfExists(state.Configuration.Model, function, syntacticArguments, state.Configuration.Resolver.EnableCaseInsensitive); IEnumerable <QueryNode> boundArguments = parsedParameters.Select(p => this.bindMethod(p)); boundArguments = boundArguments.ToList(); // force enumerable to run : will immediately evaluate all this.bindMethod(p). IEdmTypeReference returnType = function.ReturnType; IEdmEntitySetBase returnSet = null; SingleResourceNode singleEntityNode = parent as SingleResourceNode; if (singleEntityNode != null) { returnSet = function.GetTargetEntitySet(singleEntityNode.NavigationSource, state.Model); } string functionName = function.FullName(); if (returnType.IsEntity()) { boundFunction = new SingleResourceFunctionCallNode(functionName, new[] { function }, boundArguments, (IEdmEntityTypeReference)returnType.Definition.ToTypeReference(), returnSet, parent); } else if (returnType.IsStructuredCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new CollectionResourceFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, returnSet, parent); } else if (returnType.IsCollection()) { IEdmCollectionTypeReference collectionTypeReference = (IEdmCollectionTypeReference)returnType; boundFunction = new CollectionFunctionCallNode(functionName, new[] { function }, boundArguments, collectionTypeReference, parent); } else { boundFunction = new SingleValueFunctionCallNode(functionName, new[] { function }, boundArguments, returnType, parent); } return(true); }
public override ODataWriter CreateODataFeedWriter(IEdmEntitySetBase entitySet, IEdmEntityType entityType) { return new CsvWriter(this, entityType); }