public static async Task <List <ResourceResponse <Document> > > UpsertGraphDocumentsAsync(this DocumentClient client, DocumentCollection collection, IEnumerable items) { List <ResourceResponse <Document> > results = new List <ResourceResponse <Document> >(); foreach (object poco in items) { IGraphSerializer serializer = GraphSerializerFactory.CreateGraphSerializer(null, poco.GetType()); results.Add(await client.UpsertDocumentAsync(collection.SelfLink, serializer.ConvertToDocDBJObject(poco))); } return(results); }
/// <summary> /// Works simmilar to ExecuteNextAsyc<T> from IDocumentQuery<T> and allows to deserialize the results /// to custom objects of type T /// </summary> /// <typeparam name="T"></typeparam> /// <param name="gremlinQuery">ExtensionObject IDocumentQuery</param> /// <param name="context">Context that can store GraphElements. If you retrieved vertices and then an edge refering to those vertices they will be automatically linked.</param> /// <returns></returns> public static async Task <IList <T> > ExecuteNextAsyncAsPOCO <T>(this IDocumentQuery gremlinQuery, IGraphContext context = null) // where T : new() { List <T> result = new List <T>(); IGraphSerializer serializer = null; Type targetType = typeof(T); if (gremlinQuery.GetType().GenericTypeArguments[0] != typeof(Vertex)) { IDocumentQuery <Edge> edgeQuery = gremlinQuery as IDocumentQuery <Edge>; var resultSet = await edgeQuery.ExecuteNextAsync <Edge>(); foreach (Edge e in resultSet) { string typeString = GraphSerializer.GetTypePropertyString(e, out string inVTypeString, out string outVTypeString); if (String.IsNullOrEmpty(typeString)) { serializer = GraphSerializerFactory.CreateGraphSerializer(context, targetType); // Try to instantiate T } else { serializer = GraphSerializerFactory.CreateGraphSerializer(context, typeString); } serializer.Convert(e, out object edge); result.Add((T)edge); } } else { IDocumentQuery <Vertex> vertexQuery = gremlinQuery as IDocumentQuery <Vertex>; var resultSet = await vertexQuery.ExecuteNextAsync <Vertex>(); foreach (Vertex v in resultSet) { string typeString = GraphSerializer.GetTypePropertyString(v); if (String.IsNullOrEmpty(typeString)) { serializer = GraphSerializerFactory.CreateGraphSerializer(context, targetType); // Try to instantiate T } else { serializer = GraphSerializerFactory.CreateGraphSerializer(context, typeString); } serializer.Convert(v, out object vertex); result.Add((T)vertex); } } return(result); }
public async Task TestSimple() { Simple.Place cave = new Simple.Place() { name = "Cave of Hobbit" }; Simple.Place restaurant = new Simple.Place() { name = "Restaurant Green Dragon" }; Simple.Place europe = new Simple.Place() { name = "Europe", country = GraphProperty.Create("country", "AT", "MetaTag1", "Austria").AddValue("FI", "MetaTag1", "Finnland") }; Simple.Path hobbitPath = new Simple.Path(cave, restaurant, 2); //TODO: find out why 2.3 has an issue await client.CreateGraphDocumentAsync <Simple.Place>(collection, cave); await client.CreateGraphDocumentAsync <Simple.Place>(collection, restaurant); await client.CreateGraphDocumentAsync <Simple.Place>(collection, europe); await client.CreateGraphDocumentAsync <Simple.Path>(collection, hobbitPath); MemoryGraph partialGraph = new MemoryGraph(); string gremlinQueryStatement = "g.V().hasLabel('place')"; Console.WriteLine($"Executing gremlin query as string: {gremlinQueryStatement}"); var germlinQuery = client.CreateGremlinQuery <Vertex>(collection, gremlinQueryStatement); while (germlinQuery.HasMoreResults) { // It is not required to pass in a context like partialGraph here. This parameter can be omitted. foreach (var result in await germlinQuery.ExecuteNextAsyncAsPOCO <Simple.Place>(partialGraph)) { Console.WriteLine($"Vertex ==> Label:{result.Label} Name:{result.name}"); } } #region EXPERIMENTAL DEMO /// ================================================================================================= /// IMPORTANT: The following code makes use of the internal GraphTraversal class, which should not /// be used according to the documentation of Microsofts Graph Library. Use at your own risk. /// ================================================================================================= // Connect with GraphConnection object graphConnection = GraphConnectionFactory.Create(client, collection); // Drop previous context (optional if the same graph) partialGraph.Drop(); Microsoft.Azure.Graphs.GraphCommand cmd = GraphCommandFactory.Create(graphConnection); GraphTraversal placeTrav = cmd.g().V().HasLabel("place"); GraphTraversal edgeTrav = cmd.g().E().HasLabel("path"); { Console.WriteLine("Retrieving all places with 'NextAsPOCO'-Extension on GraphTraversal "); // Returns a list of all vertices for place var places = await placeTrav.NextAsPOCO <Simple.Place>(partialGraph); foreach (Simple.Place place in places) { Console.WriteLine($"Vertex ==> Label:{place.Label} Name:{place.name}"); } } // Drop previous context (optional if the same graph) partialGraph.Drop(); IGraphSerializer <Simple.Place> placeGraphSerializer = GraphSerializerFactory.CreateGraphSerializer <Simple.Place>(partialGraph); foreach (var p in placeTrav) { IList <Simple.Place> places = placeGraphSerializer.DeserializeGraphSON(p); // Returns more than one result in each call foreach (Simple.Place place in places) { Console.WriteLine($"Vertex ==> Label:{place.Label} Name:{place.name}"); Console.WriteLine("Serializing to CosmosDB internal represenation: "); string docDBJson = placeGraphSerializer.ConvertToDocDBJObject(place).ToString(); Console.WriteLine($"JSON ==> {docDBJson}"); } } Console.WriteLine("Iterating over GraphTraversal Paths (Edges) and deserializing GraphSON to custom object "); IGraphSerializer <Simple.Path> pathGraphSerializer = GraphSerializerFactory.CreateGraphSerializer <Simple.Path>(partialGraph); foreach (var p in edgeTrav) { IList <Simple.Path> paths = pathGraphSerializer.DeserializeGraphSON(p); // Returns more than one result in each loop foreach (Simple.Path path in paths) { Console.WriteLine($"Edge ==> Label:{path.Label} Weight:{path.weight}"); Console.WriteLine("Serializing to CosmosDB internal represenation: "); string docDBJson = pathGraphSerializer.ConvertToDocDBJObject(path).ToString(); Console.WriteLine($"JSON ==> {docDBJson}"); } } #endregion }
/// <summary> /// Can be called on a GraphTraversal to retrieve Vertices or Edges as custom objects. /// </summary> /// <typeparam name="T">Type of custom object that represents the Vertex or Edge</typeparam> /// <param name="trav">Extension Object GraphTraversal</param> /// <param name="context">Context that can store GraphElements. If you retrieved vertices and then an edge refering to those vertices they will be automatically linked.</param> /// <returns></returns> public static async Task <IList <T> > NextAsPOCO <T>(this GraphTraversal trav, IGraphContext context = null) // where T : new() { IGraphSerializer serializer = null; List <T> result = new List <T>(); /// Verify if the OutputFormat of the GraphCommand was set to GraphSON! Type graphTraversalType = typeof(GraphTraversal); Type targetType = typeof(T); FieldInfo outputFormatPropertyInfo = graphTraversalType.GetField("outputFormat", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); string outputFormat = outputFormatPropertyInfo.GetValue(trav).ToString(); if (!outputFormat.StartsWith("GraphSON")) { throw new Exception("OutputFormat of GraphCommand needs to be set to GRAPHSON!"); } // GraphSerializer<T> serializer = GraphSerializerFactory.CreateGraphSerializer<T>(context); // Edges and Vertices must be treated separately if (GraphSerializer.GetElementType(typeof(T)) == GraphElementType.Edge) { List <Edge> resultSet = await trav.NextAsModelAsync <Edge>(); foreach (Edge e in resultSet) { string typeString = GraphSerializer.GetTypePropertyString(e, out string inVTypeString, out string outVTypeString); if (String.IsNullOrEmpty(typeString)) { serializer = GraphSerializerFactory.CreateGraphSerializer(context, targetType); // Try to instantiate T } else { serializer = GraphSerializerFactory.CreateGraphSerializer(context, typeString); } serializer.Convert(e, out object edge); result.Add((T)edge); } } else { List <Vertex> resultSet = await trav.NextAsModelAsync <Vertex>(); foreach (Vertex v in resultSet) { string typeString = GraphSerializer.GetTypePropertyString(v); if (String.IsNullOrEmpty(typeString)) { serializer = GraphSerializerFactory.CreateGraphSerializer(context, targetType); // Try to instantiate T } else { serializer = GraphSerializerFactory.CreateGraphSerializer(context, typeString); } serializer.Convert(v, out object vertex); result.Add((T)vertex); } //Alternative implementation TODO: Measure speed //========================== //foreach (var graphSON in trav) //{ // List<T> partialResult = serializer.DeserializeGraphSON(graphSON); // foreach (T r in partialResult) // result.Add(r); //} } return(result); }
public static async Task <ResourceResponse <Document> > UpsertGraphDocumentAsync <T>(this DocumentClient client, DocumentCollection collection, T poco) { IGraphSerializer serializer = GraphSerializerFactory.CreateGraphSerializer(null, poco.GetType()); return(await client.UpsertDocumentAsync(collection.SelfLink, serializer.ConvertToDocDBJObject(poco))); }
public static async Task <ResourceResponse <Document> > CreateGraphDocumentAsync <T>(this DocumentClient client, DocumentCollection collection, T poco) where T : new() { IGraphSerializer <T> serializer = GraphSerializerFactory.CreateGraphSerializer <T>(); return(await client.CreateDocumentAsync(collection.SelfLink, serializer.ConvertToDocDBJObject(poco))); }
static async Task Demo() { try { Console.WriteLine("========================================================="); Console.WriteLine("Demo for the SpectoLogic.Azure.CosmosDB Extension Library"); Console.WriteLine("(c) by SpectoLogic e.U. 2017"); Console.WriteLine("written by Andreas Pollak"); Console.WriteLine("Licensed under the MIT License"); Console.WriteLine("========================================================="); // Connect with DocumentClient and create necessary Database and Collection Console.Write("Creating Collection 'thehobbit'..."); DocumentClient client = await CosmosDBHelper.ConnectToCosmosDB(Account_DemoBuild_Hobbit, Account_DemoBuild_Hobbit_Key); Database db = await CosmosDBHelper.CreateOrGetDatabase(client, "demodb"); DocumentCollection collection = await CosmosDBHelper.CreateCollection(client, db, "thehobbit", 400, null, null, false); Console.WriteLine("Done"); Console.WriteLine("---------------------------------------------------------"); Console.WriteLine("DEMO: Delivery Demo "); Console.WriteLine("---------------------------------------------------------"); Delivery.Demo d = new Delivery.Demo(); await d.Execute(client, collection); Console.WriteLine("---------------------------------------------------------"); Console.WriteLine("DEMO: Create custom objects and populate cosmosdb graph"); Console.WriteLine("---------------------------------------------------------"); Place cave = new Place() { name = "Cave of Hobbit" }; Place restaurant = new Place() { name = "Restaurant Green Dragon" }; Place europe = new Place() { name = "Europe", country = GraphProperty.Create("country", "AT", "MetaTag1", "Austria").AddValue("FI", "MetaTag1", "Finnland") }; Path hobbitPath = new Path(cave, restaurant, 2); //TODO: find out why 2.3 has an issue await client.CreateGraphDocumentAsync <Place>(collection, cave); await client.CreateGraphDocumentAsync <Place>(collection, restaurant); await client.CreateGraphDocumentAsync <Place>(collection, europe); await client.CreateGraphDocumentAsync <Path>(collection, hobbitPath); Console.WriteLine("----------------------------------------------------------------------------------"); Console.WriteLine("DEMO: Usage of 'ExecuteNextAsyncAsPOCO<T>'-Extension Method on typed Gremlin Query"); Console.WriteLine("----------------------------------------------------------------------------------"); MemoryGraph partialGraph = new MemoryGraph(); string gremlinQueryStatement = "g.V().hasLabel('place')"; Console.WriteLine($"Executing gremlin query as string: {gremlinQueryStatement}"); var germlinQuery = client.CreateGremlinQuery <Vertex>(collection, gremlinQueryStatement); while (germlinQuery.HasMoreResults) { // It is not required to pass in a context like partialGraph here. This parameter can be omitted. foreach (var result in await germlinQuery.ExecuteNextAsyncAsPOCO <Place>(partialGraph)) { Console.WriteLine($"Vertex ==> Label:{result.Label} Name:{result.name}"); } } #region EXPERIMENTAL DEMO /// ================================================================================================= /// IMPORTANT: The following code makes use of the internal GraphTraversal class, which should not /// be used according to the documentation of Microsofts Graph Library. Use at your own risk. /// ================================================================================================= Console.WriteLine("--------------------------------------------------------------------"); Console.WriteLine("DEMO: Usage of 'NextAsPOCO<T>' with GraphCommand and GraphTraversal "); Console.WriteLine("--------------------------------------------------------------------"); Console.Write("Connecting with GraphConnection object..."); // Connect with GraphConnection object graphConnection = GraphConnectionFactory.Create(client, collection); Console.WriteLine("Done"); // Drop previous context (optional if the same graph) partialGraph.Drop(); Microsoft.Azure.Graphs.GraphCommand cmd = GraphCommandFactory.Create(graphConnection); GraphTraversal placeTrav = cmd.g().V().HasLabel("place"); GraphTraversal edgeTrav = cmd.g().E().HasLabel("path"); { Console.WriteLine("Retrieving all places with 'NextAsPOCO'-Extension on GraphTraversal "); // Returns a list of all vertices for place var places = await placeTrav.NextAsPOCO <Place>(partialGraph); foreach (Place place in places) { Console.WriteLine($"Vertex ==> Label:{place.Label} Name:{place.name}"); } } Console.WriteLine("--------------------------------------------------------------------"); Console.WriteLine("DEMO: Direct Usage of GraphSerializer<T> with GraphTraversal "); Console.WriteLine("--------------------------------------------------------------------"); // Drop previous context (optional if the same graph) partialGraph.Drop(); Console.WriteLine("Iterating over GraphTraversal Places (Vertices) and deserializing GraphSON to custom object "); IGraphSerializer <Place> placeGraphSerializer = GraphSerializerFactory.CreateGraphSerializer <Place>(partialGraph); foreach (var p in placeTrav) { IList <Place> places = placeGraphSerializer.DeserializeGraphSON(p); // Returns more than one result in each call foreach (Place place in places) { Console.WriteLine($"Vertex ==> Label:{place.Label} Name:{place.name}"); Console.WriteLine("Serializing to CosmosDB internal represenation: "); string docDBJson = placeGraphSerializer.ConvertToDocDBJObject(place).ToString(); Console.WriteLine($"JSON ==> {docDBJson}"); } } Console.WriteLine("Iterating over GraphTraversal Paths (Edges) and deserializing GraphSON to custom object "); IGraphSerializer <Path> pathGraphSerializer = GraphSerializerFactory.CreateGraphSerializer <Path>(partialGraph); foreach (var p in edgeTrav) { IList <Path> paths = pathGraphSerializer.DeserializeGraphSON(p); // Returns more than one result in each loop foreach (Path path in paths) { Console.WriteLine($"Edge ==> Label:{path.Label} Weight:{path.weight}"); Console.WriteLine("Serializing to CosmosDB internal represenation: "); string docDBJson = pathGraphSerializer.ConvertToDocDBJObject(path).ToString(); Console.WriteLine($"JSON ==> {docDBJson}"); } } #endregion } catch (Exception ex) { Console.WriteLine("\nError:"); Console.WriteLine($"Demo failed with {ex.Message}."); } }