示例#1
0
        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));
            }
        }
示例#2
0
        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);
        }
示例#4
0
        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));
        }
示例#10
0
            public override IEnumerable <IOgmConnection> MergeConnections(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities)
            {
                ConnectionMerge.Clear();
                ConnectionMerge.AddRange(entities);

                return(entities.Select(p => p.Item1));
            }
示例#11
0
            public override IEnumerable <IOgmConnection> UpdateRels(IStatementRunner runner, IEnumerable <Tuple <IOgmConnection, IEnumerable <string> > > entities)
            {
                UpdatedRels.Clear();
                UpdatedRels.AddRange(entities);

                return(entities.Select(p => p.Item1));
            }
示例#12
0
            public override IEnumerable <IOgmEntity> UpdateNodes(IStatementRunner runner, IEnumerable <Tuple <IOgmEntity, IEnumerable <string> > > entities)
            {
                UpdatedNodes.Clear();
                UpdatedNodes.AddRange(entities);

                return(entities.Select(p => p.Item1));
            }
示例#13
0
        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());
        }
示例#15
0
        /// <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);
        }
示例#16
0
            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());
            }
示例#17
0
        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));
            }
        }
示例#18
0
            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);
     }
 }
示例#22
0
        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());
            }
        }
示例#23
0
        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));
            }
        }
示例#25
0
        /// <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);
        }