public override IEnumerable <IOgmConnection> CreateRels(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities) { runner = runner ?? throw new ArgumentNullException(nameof(runner)); entities = entities ?? throw new ArgumentNullException(nameof(entities)); entities = entities.Where(p => p?.Item1 != null); if (entities.Count() == 0) { return(null); } IGraphManagedStatementRunner mgr = (runner as IGraphManagedStatementRunner) ?? throw new ArgumentException("The statement must be decorated.", nameof(runner)); using (ManagerAccess.Manager.ScopeOMnG()) { Symbol row = new Symbol(); Symbol m = new Symbol(); Symbol s = new Symbol(); Symbol d = new Symbol(); StringBuilder sb = new StringBuilder(); sb.Append($"UNWIND $batch AS {row} "); sb.Append($"MATCH ({s} {{{nameof(IOgmEntity.EntityId)}:{row}.{nameof(RelEntity.SourceId)}}})"); sb.Append($"MATCH ({d} {{{nameof(IOgmEntity.EntityId)}:{row}.{nameof(RelEntity.DestinationId)}}})"); sb.Append($"CALL apoc.create.relationship({s}, {row}.{nameof(RelEntity.Label)}, {row}.{nameof(RelEntity.Properties)}, {d}) yield rel AS {m} "); sb.Append($"SET {m}.{nameof(IOgmEntity.EntityId)}=id({m}) "); sb.Append($"RETURN {m}"); return(runner.ExecuteQuery <IOgmEntity>(sb.ToString(), new { batch = entities.Select(p => new RelEntity(p.Item1, p.Item1.Source.EntityId.Value, p.Item1.Destination.EntityId.Value, false, excludePorperties: p.Item2).ToPropDictionary()).ToList() }).ToList().Select(p => p as IOgmConnection)); } }
public override IEnumerable <IOgmConnection> UpdateRels(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities) { runner = runner ?? throw new ArgumentNullException(nameof(runner)); entities = entities ?? throw new ArgumentNullException(nameof(entities)); entities = entities.Where(p => p?.Item1?.EntityId != null); if (entities.Count() == 0) { return(null); } IGraphManagedStatementRunner mgr = (runner as IGraphManagedStatementRunner) ?? throw new ArgumentException("The statement must be decorated.", nameof(runner)); using (ManagerAccess.Manager.ScopeOMnG()) { Symbol row = new Symbol(); Symbol m = new Symbol(); StringBuilder sb = new StringBuilder(); sb.Append($"UNWIND $batch AS {row} "); sb.Append($"MATCH ()-[{m} {{{nameof(IOgmEntity.EntityId)}:{row}.{nameof(IOgmEntity.EntityId)}}}]->()"); sb.Append($"SET {m}+={row}.{nameof(RelEntity.Properties)} "); sb.Append($"RETURN {m}"); return(runner.ExecuteQuery <IOgmEntity>(sb.ToString(), new { batch = entities.Select(p => new RelEntity(p.Item1, -1, -1, excludePorperties: p.Item2).ToPropDictionary()).ToList() }).ToList().Select(p => p as IOgmConnection)); } }
/// <summary> /// Add simple index on type property. /// </summary> public static void AddIndex(this IStatementRunner statementRunner, string typeName, string propertyName) { propertyName = propertyName.ToCamelCase(); var statement = $"CREATE INDEX ON: {typeName}({propertyName})"; statementRunner.Run(statement); }
public override IEnumerable <IOgmEntity> CreateNodes(IStatementRunner runner, IEnumerable <Tuple <IOgmEntity, IEnumerable <string> > > entities) { runner = runner ?? throw new ArgumentNullException(nameof(runner)); entities = entities ?? throw new ArgumentNullException(nameof(entities)); entities = entities.Where(p => p != null); if (entities.Count() == 0) { return(null); } IGraphManagedStatementRunner mgr = (runner as IGraphManagedStatementRunner) ?? throw new ArgumentException("The statement must be decorated.", nameof(runner)); using (ManagerAccess.Manager.ScopeOMnG()) { Symbol row = new Symbol(); Symbol m = new Symbol(); StringBuilder sb = new StringBuilder(); sb.Append($"UNWIND $batch AS {row} "); sb.Append($"CALL apoc.create.node({row}.{nameof(NodeEntity.Labels)}, {row}.{nameof(NodeEntity.Properties)}) yield node AS {m} "); sb.Append($"SET {m}.{nameof(IOgmEntity.EntityId)}=id({m}) "); sb.Append($"RETURN {m}"); return(runner.ExecuteQuery <IOgmEntity>(sb.ToString(), new { batch = entities.Select(p => new NodeEntity(p.Item1, false, excludePorperties: p.Item2).ToPropDictionary()).ToList() }).ToList()); } }
public static IEnumerable <T> ExecuteQuery <T, T1, T2>(this IStatementRunner ext, string query, Func <T, T1, T2, T> map, object param = null) where T : class where T1 : class where T2 : class { ext = ext ?? throw new ArgumentNullException(nameof(ext)); map = map ?? throw new ArgumentNullException(nameof(map)); if (typeof(T).IsCollection() && !typeof(T).IsEnumerable()) { throw new InvalidOperationException("To map collections use IEnumerable`1"); } if (typeof(T1).IsCollection() && !typeof(T1).IsEnumerable()) { throw new InvalidOperationException("To map collections use IEnumerable`1"); } if (typeof(T2).IsCollection() && !typeof(T2).IsEnumerable()) { throw new InvalidOperationException("To map collections use IEnumerable`1"); } return(new QueryableNeo4jStatement <T>( ext, () => GetStatement(query, param, ext), (result, t) => { return map( (T)ext.AsManaged().ParseRecord(result.Values[result.Keys[0]], typeof(T), t), (T1)ext.AsManaged().ParseRecord(result.Values[result.Keys[1]], typeof(T1), typeof(T1)), (T2)ext.AsManaged().ParseRecord(result.Values[result.Keys[2]], typeof(T2), typeof(T2)) ); })); }
public static IResultSummary DeleteNode <T>(this IStatementRunner ext, T entity, Expression <Func <T, object> > propMatch = null) where T : class { ext = ext ?? throw new ArgumentNullException(nameof(ext)); entity = entity ?? throw new ArgumentNullException(nameof(entity)); IEnumerable <string> keyOn = propMatch?.ToPropertyNameCollection() ?? entity.GetType().GetProperties().Select(p => p.Name); if (keyOn.Count() > 0) { foreach (string name in keyOn) { PropertyInfo pinfo = typeof(T).GetProperty(name); if (ObjectExtensions.Configuration.Get(pinfo, entity) == pinfo.PropertyType.GetDefault()) { throw new ArgumentException($"Every selection matching property must be set. '{name}' has its default type value."); } } } Symbol s = new Symbol(); Node n = new Node(s, typeof(T), entity.SelectProperties(keyOn)); n.Parametrize(prefix: "value."); return(ext.Execute( $"MATCH {n.BuildForQuery()} " + $"DETACH DELETE {s}", new { value = entity })); }
public static IEnumerable <IEnumerable <T> > ExecuteQuery <T, T1, T2>(this IStatementRunner ext, Func <qu.IQueryBuilder, string> query, Func <T, T1, T2, T> map, params object[] param) where T : class where T1 : class where T2 : class { return(ext.ExecuteQuery <T, T1, T2>(query(new qu.QueryBuilder()), map, param)); }
public static Task AsAsync(this IStatementRunner ext, Action <IStatementRunner> operation) { ext = ext ?? throw new ArgumentNullException(nameof(ext)); operation = operation ?? throw new ArgumentNullException(nameof(operation)); return(Task.Run(() => operation(ext))); }
public static Task <T> AsAsync <T>(this IStatementRunner ext, Func <IStatementRunner, T> operation, CancellationToken cancellationToken) { ext = ext ?? throw new ArgumentNullException(nameof(ext)); operation = operation ?? throw new ArgumentNullException(nameof(operation)); return(Task.Run <T>(() => operation(ext), cancellationToken)); }
public override IEnumerable <IOgmConnection> MergeConnections(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities) { ConnectionMerge.Clear(); ConnectionMerge.AddRange(entities); return(entities.Select(p => p.Item1)); }
public override IEnumerable <IOgmConnection> UpdateRels(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities) { UpdatedRels.Clear(); UpdatedRels.AddRange(entities); return(entities.Select(p => p.Item1)); }
public override IEnumerable <IOgmEntity> UpdateNodes(IStatementRunner runner, IEnumerable <Tuple <IOgmEntity, IEnumerable <string> > > entities) { UpdatedNodes.Clear(); UpdatedNodes.AddRange(entities); return(entities.Select(p => p.Item1)); }
public override void DeleteRels(IStatementRunner runner, IEnumerable <IOgmConnection> entities) { runner = runner ?? throw new ArgumentNullException(nameof(runner)); entities = entities ?? throw new ArgumentNullException(nameof(entities)); entities = entities.Where(p => p?.EntityId != null); if (entities.Count() == 0) { return; } IGraphManagedStatementRunner mgr = (runner as IGraphManagedStatementRunner) ?? throw new ArgumentException("The statement must be decorated.", nameof(runner)); using (ManagerAccess.Manager.ScopeOMnG()) { Symbol row = new Symbol(); Symbol m = new Symbol(); StringBuilder sb = new StringBuilder(); sb.Append($"UNWIND $batch AS {row} "); sb.Append($"MATCH ()-[{m} {{{nameof(IOgmEntity.EntityId)}:{row}}}]->()"); sb.Append($"DELETE {m}"); runner.Execute(sb.ToString(), new { batch = entities.Select(p => p.EntityId).ToList() }); } }
public static T AddOrUpdateNode <T>(this IStatementRunner ext, T entity, Expression <Func <T, object> > propMatch = null) where T : class { ext = ext ?? throw new ArgumentNullException(nameof(ext)); entity = entity ?? throw new ArgumentNullException(nameof(entity)); IEnumerable <string> keyOn = propMatch?.ToPropertyNameCollection() ?? new string[0]; if (keyOn.Count() > 0) { foreach (string name in keyOn) { PropertyInfo pinfo = typeof(T).GetProperty(name); if (ObjectExtensions.Configuration.Get(pinfo, entity) == pinfo.PropertyType.GetDefault()) { throw new ArgumentException($"Every selection matching property must be set. '{name}' has its default type value."); } } } Symbol s = new Symbol(); Node n = new Node(s, typeof(T), entity.SelectProperties(keyOn)); n.Parametrize(prefix: "value."); return(ext.ExecuteQuery <T>( $"MERGE {n} " + $"ON CREATE SET {s}+=$value,{s}.{nameof(IOgmEntity.EntityId)}=id({s}) " + $"ON MATCH SET {s}+=$value,{s}.{nameof(IOgmEntity.EntityId)}=id({s}) " + $"RETURN {s}", new { value = entity.SelectMatchingTypesProperties(p => p.IsPrimitive() || p.IsOfGenericType(typeof(IEnumerable <>), t => t.Type.IsPrimitive())) }).FirstOrDefault()); }
/// <summary> /// This constructor is called by the client to create the data source. /// </summary> public QueryableNeo4jStatement(IStatementRunner runner, Func <Statement> statement, Func <IRecord, Type, object> mapper) { Runner = runner ?? throw new ArgumentNullException(nameof(runner)); Statement = statement ?? throw new ArgumentNullException(nameof(statement)); Mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); Provider = new CypherQueryProvider(runner, statement, mapper); Expression = Expression.Constant(this); }
private IResultSummary Execute(IStatementRunner runner, string statement) { var result = runner.Run(statement); Thread.Sleep(_rnd.Next(100)); result.Summary(); Thread.Sleep(_rnd.Next(100)); return(result.Summary()); }
public static IEnumerable <T> Query <T>(this IStatementRunner session, string cypher) { var forLookup = new PreparedStatement <T>(cypher); var ps = (PreparedStatement <T>)PreparedStatements.GetOrAdd(forLookup.GetHashCode(), hash => forLookup); foreach (var record in session.Run(cypher)) { yield return(ps.Map(record)); } }
public override IEnumerable <IOgmEntity> CreateNodes(IStatementRunner runner, IEnumerable <Tuple <IOgmEntity, IEnumerable <string> > > entities) { CreatedNodes.Clear(); CreatedNodes.AddRange(entities); foreach (var item in entities) { item.Item1.EntityId = CurrentId++; } return(entities.Select(p => p.Item1)); }
public static IQueryable <T> GetQueryableNodeSet <T>(this IStatementRunner ext) where T : class { ext = ext ?? throw new ArgumentNullException(nameof(ext)); Symbol s = new Symbol(); Node n = new Node(s, typeof(T)); return(ext.ExecuteQuery <T>( $"MATCH {n.BuildForQuery()} " + $"RETURN {s}")); }
private void DeleteNodes(IStatementRunner runner) { int deletedNodes; do { var statement = $"MATCH (n) WITH n LIMIT {BatchSizeDelete} DETACH DELETE n"; var result = runner.Run(statement); deletedNodes = result.Summary.Counters.NodesDeleted; } while (deletedNodes == BatchSizeDelete); }
protected EntityManagerBase SelectManager(IStatementRunner runner) { if (Managers?.Any(p => p.Key(runner)) ?? false) { return(Managers.First(p => p.Key(runner)).Value); } else { return(Default); } }
public override IEnumerable <IOgmConnection> CreateRels(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities) { runner = runner ?? throw new ArgumentNullException(nameof(runner)); entities = entities ?? throw new ArgumentNullException(nameof(entities)); entities = entities.Where(p => p?.Item1 != null); if (entities.Count() == 0) { return(null); } IGraphManagedStatementRunner mgr = (runner as IGraphManagedStatementRunner) ?? throw new ArgumentException("The statement must be decorated.", nameof(runner)); List <IGrouping <Type, Tuple <int, Type, RelEntity> > > sets = entities .Select((p, i) => new Tuple <int, Type, RelEntity>( i, p.Item1.GetType(), new RelEntity(p.Item1, p.Item1.Source.EntityId.Value, p.Item1.Destination.EntityId.Value, false, p.Item2))) .GroupBy(p => p.Item2).ToList(); List <Tuple <int, IOgmEntity> > results = new List <Tuple <int, IOgmEntity> >(); using (ManagerAccess.Manager.ScopeOMnG()) { foreach (var set in sets) { List <Tuple <int, Type, RelEntity> > items = set.ToList(); Symbol row = new Symbol(); Symbol m = new Symbol(); Symbol s = new Symbol(); Symbol d = new Symbol(); StringBuilder sb = new StringBuilder(); sb.Append($"UNWIND $batch AS {row} "); sb.Append($"MATCH ({s} {{{nameof(IOgmEntity.EntityId)}:{row}.{nameof(RelEntity.SourceId)}}}) "); sb.Append($"MATCH ({d} {{{nameof(IOgmEntity.EntityId)}:{row}.{nameof(RelEntity.DestinationId)}}}) "); sb.Append($"CREATE ({s})-{new Rel(m, set.Key)}->({d}) "); sb.Append($"SET {m}+={row}.{nameof(RelEntity.Properties)},{m}.{nameof(IOgmEntity.EntityId)}=id({m}) "); sb.Append($"RETURN {m}"); results.AddRange(runner .ExecuteQuery <IOgmEntity>(sb.ToString(), new { batch = items.Select(p => p.Item3.ToPropDictionary()).ToList() }) .ToList() .Select((p, i) => new Tuple <int, IOgmEntity>(items[i].Item1, p))); } return(results.OrderBy(p => p.Item1).Select(p => p.Item2 as IOgmConnection).ToList()); } }
private IList <Edge> GetEdges(IStatementRunner runner) { log.Debug("Retrieving edges..."); var result = runner.Run(GetEdgesCypher); log.Debug("Done."); return(result.Select(rec => new Edge { Vertex1 = Convert.ToInt32(rec["n.id"]), Vertex2 = Convert.ToInt32(rec["m.id"]) }).ToList()); }
private static Statement GetStatement(string query, object param, IStatementRunner runner) { query = query ?? throw new ArgumentNullException(nameof(query)); if (param != null) { return(new Statement(query, param.ToPropDictionary())); } else { return(new Statement(query)); } }
/// <summary> /// This constructor is called by Provider.CreateQuery(). /// </summary> /// <param name="expression"></param> public QueryableNeo4jStatement(IStatementRunner runner, Func <Statement> statement, Func <IRecord, Type, object> mapper, CypherQueryProvider provider, Expression expression) : this(runner, statement, mapper) { provider = provider ?? throw new ArgumentNullException(nameof(provider)); expression = expression ?? throw new ArgumentNullException(nameof(expression)); if (!typeof(IQueryable <TData>).IsAssignableFrom(expression.Type)) { throw new ArgumentOutOfRangeException(nameof(expression)); } Provider = provider; Expression = expression; }
public static IEnumerable <IEnumerable <T> > ExecuteQuery <T, T1>(this IStatementRunner ext, string query, Func <T, T1, T> map, params object[] param) where T : class where T1 : class { if (param == null || param.Length == 0) { yield break; } foreach (object item in param) { yield return(ext.ExecuteQuery <T, T1>(query, map, item)); } }
/// <summary> /// Add POCO object as node in Neo4j database. /// All public properties will automatically be added as properties of the node. /// Please note that it is NOT merely a concatenated string that is executed! /// To avoid injection attacks the parameters are properly inserted through a value array. /// </summary> /// <param name="statementRunner">Either a session or a transation to execute the statement</param> /// <param name="obj">Generic POCO object</param> /// <param name="label">Specify type name to be used. Skip if you are satisfied with object type name.</param> /// <param name="i">Optional counter if used from collection. Only used for logging.</param> public static int AddNode(this IStatementRunner statementRunner, object obj, string label, int?i = null) { // CREATE (:TypeName { propertyName1: propertyValue, propertyName2: propertyValue2 } )"; label = label ?? obj.GetType().Name; var parameters = obj.GetProperties(); var valuePairs = string.Join(", ", parameters.Select(p => $"{p.Key}: {{{p.Key}}}")); var statement = $"CREATE (x:{label} {{{valuePairs}}} ) RETURN x"; var result = statementRunner.Run(statement, parameters); var node = (INode)result.Single().As <IRecord>()["x"]; var nodeCounter = i.HasValue && i.Value > 1 ? $"({i})" : string.Empty; Console.WriteLine($"{string.Join(",", node.Labels)} node created with Id={node.Id} and {node.Properties.Count} properties {nodeCounter}"); return(result.Summary.Counters.NodesCreated); }
public static IEnumerable <IResultSummary> Execute(this IStatementRunner ext, string query, params object[] param) { ext = ext ?? throw new ArgumentNullException(nameof(ext)); query = query ?? throw new ArgumentNullException(nameof(query)); if (param == null || param.Length == 0) { yield break; } foreach (object item in param) { yield return(ext.Execute(query, item)); } }
private void DeleteIndexes(IStatementRunner runner) { var indexResult = runner.Run("CALL db.indexes()"); using (var enumerator = indexResult.GetEnumerator()) { while (enumerator.MoveNext()) { var record = enumerator.Current; if (record != null) { var statement = $"DROP {record.Values["description"]} "; runner.Run(statement); } } } }
/// <summary> /// Add relation between nodes. /// </summary> /// <typeparam name="T">Type used for relation record</typeparam> /// <param name="statementRunner">Either a session or a transation to execute the statement</param> /// <param name="relation">Object used as relation specifier</param> /// <param name="mappingConfig">Description on how to interpret record object</param> /// <param name="i">Optional counter if used from collection. Only used for logging.</param> public static int AddRelation <T>(this IStatementRunner statementRunner, T relation, MappingConfig mappingConfig, int?i = null) { // MATCH (f:FromNodeType), (t:ToNodeType) // WHERE f.FromPropertyName = 'FromPropertyValue' AND t.ToPropertyName = 'ToPropertyValue' // CREATE (f)-[r:RELATIONTYPE]->(t) // RETURN r var parameters = relation.GetProperties(); var fromPropertyName = nameof(IRelation.FromId).ToCamelCase(); var toPropertyName = nameof(IRelation.ToId).ToCamelCase(); var fromPropertyValue = parameters[fromPropertyName]; var toPropertyValue = parameters[toPropertyName]; var properties = parameters.Where(p => p.Key != fromPropertyName && p.Key != toPropertyName).ToDictionary(p => p.Key, p => p.Value); var valuePairs = string.Join(", ", properties.Select(p => $"{p.Key}: {{{p.Key}}}")); var statement = $"MATCH (f:{mappingConfig.FromNode}), (t:{mappingConfig.ToNode}) WHERE f.{mappingConfig.FromProperty}={fromPropertyValue} AND t.{mappingConfig.ToProperty}={toPropertyValue} CREATE (f)-[r:{mappingConfig.RelationName} {{{valuePairs}}}]->(t) RETURN r"; var result = statementRunner.Run(statement, properties); var relationship = (IRelationship)result.Single().As <IRecord>()["r"]; var relationCounter = i.HasValue ? $"({i})" : string.Empty; Console.WriteLine($"{relationship.Type} relation created with Id={relationship.Id} and {relationship.Properties.Count} properties {relationCounter}"); return(result.Summary.Counters.RelationshipsCreated); }