Last active
March 6, 2018 19:15
-
-
Save kbastani/9444652 to your computer and use it in GitHub Desktop.
Neo4j Transactional Endpoint Implementation for C# .NET
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Neo4jClient; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Runtime.Serialization.Json; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Arktera.Core.Graph.Utilities.TransactionalEndpoint | |
{ | |
/// <summary> | |
/// Cypher statement containing a string Cypher query template and a list of parameters. | |
/// </summary> | |
public class Statement | |
{ | |
/// <summary> | |
/// The Cypher template containing parameter placeholders. | |
/// </summary> | |
public string statement { get; set; } | |
/// <summary> | |
/// A key/value list of parameters and their values to be injected into the Cypher template. | |
/// </summary> | |
public Dictionary<string, object> parameters { get; set; } | |
} | |
/// <summary> | |
/// A Neo4j TransactionRequest object to be posted to the Neo4j transactional endpoint. | |
/// </summary> | |
public class TransactionRequest | |
{ | |
/// <summary> | |
/// A list of Neo4j Cypher statements to be sent to the Neo4j transactional endpoint. | |
/// </summary> | |
public List<Statement> statements { get; set; } | |
} | |
/// <summary> | |
/// The response data for a Neo4j transactional endpoint response. | |
/// </summary> | |
public class Datum | |
{ | |
/// <summary> | |
/// A list of key/values returned from the transactional endpoint request. | |
/// </summary> | |
public List<string> row { get; set; } | |
} | |
/// <summary> | |
/// The result wrapper for the Neo4j transactional endpoint response. | |
/// </summary> | |
public class Result | |
{ | |
/// <summary> | |
/// A list of columns in the Neo4j transactional endpoint response. | |
/// </summary> | |
public List<string> columns { get; set; } | |
/// <summary> | |
/// A list of datum from the Neo4j transactional endpoint response. | |
/// </summary> | |
public List<Datum> data { get; set; } | |
} | |
/// <summary> | |
/// The transaction response object containing an expiration context for the Neo4j transactional endpoint response. | |
/// </summary> | |
public class Transaction | |
{ | |
/// <summary> | |
/// The expiration time of the current Neo4j transactional endpoint response. | |
/// </summary> | |
public string expires { get; set; } | |
} | |
/// <summary> | |
/// The TransactionResponse class contains properties that bind to a Neo4j transactional endpoint response. | |
/// </summary> | |
public class TransactionResponse | |
{ | |
/// <summary> | |
/// Contains a URI to the Neo4j REST API to commit the current transaction within context of this class. | |
/// </summary> | |
public string commit { get; set; } | |
/// <summary> | |
/// A list of result objects containing data for each transaction statement in the context of this class. | |
/// </summary> | |
public List<Result> results { get; set; } | |
/// <summary> | |
/// The Transaction object contains the expiration time for the transactional endpoint response in the context of this class. | |
/// </summary> | |
public Transaction transaction { get; set; } | |
/// <summary> | |
/// A list of errors returned from the Neo4j transactional endpoint. | |
/// </summary> | |
public List<object> errors { get; set; } | |
} | |
public class Neo4jTransactionUtility | |
{ | |
/// <summary> | |
/// Execute a transaction on Neo4j's transactional endpoint. | |
/// </summary> | |
/// <param name="request">The TransactionRequest object containing statements to be transacted over the Neo4j graph.</param> | |
/// <returns>Returns a TransactionResponse object containing the response from Neo4j transactional endpoint.</returns> | |
public static TransactionResponse ExecuteTransaction(TransactionRequest request) | |
{ | |
// Instantiate response object | |
TransactionResponse response = default(TransactionResponse); | |
// Post commit transaction to the server | |
response = Post("/transaction", request); | |
// Return the response to the calling class | |
return response; | |
} | |
/// <summary> | |
/// Commit a transaction on Neo4j's transactional endpoint with a supplied open TransactionResponse object. | |
/// </summary> | |
/// <param name="openTransaction">An open transaction on the Neo4j transactional endpoint.</param> | |
/// <param name="request">A TransactionRequest object containing any statements that should be run before the transaction is committed.</param> | |
/// <returns></returns> | |
public static TransactionResponse CommitTransaction(TransactionResponse openTransaction, TransactionRequest request) | |
{ | |
// Instantiate response object | |
TransactionResponse response = default(TransactionResponse); | |
// Post commit transaction to the server | |
response = Post(openTransaction.commit, request); | |
// Return the response to the calling class | |
return response; | |
} | |
/// <summary> | |
/// HTTP POST a transaction to the transactional endpoint via the Neo4j REST API. | |
/// </summary> | |
/// <param name="endpoint">The endpoint URI to HTTP POST to.</param> | |
/// <param name="request">The TransactionRequest object containing statements to be executed or committed.</param> | |
/// <returns>Returns a TransactionResponse object containing the results of the transaction.</returns> | |
private static TransactionResponse Post(string endpoint, TransactionRequest request) | |
{ | |
// Instantiate response object | |
TransactionResponse response = default(TransactionResponse); | |
// Get authenticated graph client | |
GraphClient graphClient = CloudGraph.GetNeo4jGraphClient(); | |
// Initialize Neo4j cypher transaction context | |
CypherFluentQueryCreator cypher = new CypherFluentQueryCreator(graphClient, new Uri(CloudGraph.GetDatabaseUri())); | |
cypher.Connect(); | |
// Initialize HTTP request message | |
HttpRequestMessage requestMessage = cypher.HttpPostAsJson(endpoint, request); | |
requestMessage.Headers.Remove("Accept-Encoding"); | |
requestMessage.Headers.Add("Accept-Encoding", "UTF-8"); | |
// Initialize the response message from the Cypher transactional context | |
HttpResponseMessage responseMessage = cypher.SendHttpRequestAsync(requestMessage, HttpStatusCode.OK).Result; | |
if (responseMessage.Content.ReadAsStreamAsync().Result.Length > 0) | |
{ | |
// Get the response string | |
string responseString = Encoding.UTF8.GetString(responseMessage.Content.ReadAsByteArrayAsync().Result); | |
// Deseriaize the response from the HTTP REST request into a TransactionResponse object | |
response = (TransactionResponse)(new DataContractJsonSerializer(typeof(TransactionResponse)) | |
.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(responseString)))); | |
} | |
return response; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// A test for the Neo4j transactional endpoint wrapper | |
///</summary> | |
[TestMethod()] | |
public void TransactionalEndpointTest() | |
{ | |
string cypher = "MATCH (thing:Thing)\n" + | |
"WHERE thing.Key = {key}\n" + | |
"MATCH (thing)-[:CONTENT]->(content)\n" + | |
"WITH thing.Key as key, content.Content as sentence\n" + | |
"RETURN DISTINCT key, sentence"; | |
Dictionary<string, object> parameters = new Dictionary<string,object>(); | |
parameters.Add("key", "AND THE VALUE OF INFORMATION GOES"); | |
// Open a transaction and post the Cypher statement and parameters above | |
TransactionResponse transactionResponse = Neo4jTransactionUtility.ExecuteTransaction(new TransactionRequest() | |
{ | |
statements = new List<Statement>() { | |
new Statement() { | |
parameters = parameters, | |
statement = cypher | |
} | |
} | |
}); | |
Assert.IsNotNull(transactionResponse); | |
// Commit the transaction | |
TransactionResponse finalTxResponse = Neo4jTransactionUtility | |
.CommitTransaction(transactionResponse, new TransactionRequest() { statements = new List<Statement>() }); | |
Assert.IsNotNull(finalTxResponse); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment