예제 #1
0
        public override void Update(OGM item)
        {
            Transaction trans  = Transaction.RunningTransaction;
            Entity      entity = item.GetEntity();

            string match;
            Dictionary <string, object?> parameters = new Dictionary <string, object?>();

            parameters.Add("key", item.GetKey());

            if (entity.RowVersion == null)
            {
                match = string.Format("MATCH (node:{0}) WHERE node.{1} = {{key}} SET node = {{newValues}}", entity.Label.Name, entity.Key.Name);
            }
            else
            {
                parameters.Add("lockId", Conversion <DateTime, long> .Convert(item.GetRowVersion()));
                match = string.Format("MATCH (node:{0}) WHERE node.{1} = {{key}} AND node.{2} = {{lockId}} SET node = {{newValues}}", entity.Label.Name, entity.Key.Name, entity.RowVersion.Name);
                item.SetRowVersion(trans.TransactionDate);
            }

            IDictionary <string, object?> node = item.GetData();

            parameters.Add("newValues", node);

            Dictionary <string, object?>?customState = null;
            var args = entity.RaiseOnNodeUpdate(trans, item, match, parameters, ref customState);

            RawResult result = trans.Run(args.Cypher, args.Parameters);

            if (!result.Statistics().ContainsUpdates)
            {
                throw new DBConcurrencyException($"The {entity.Name} with {entity.Key.Name} '{item.GetKey()?.ToString() ?? "<NULL>"}' was changed or deleted by another process or thread.");
            }

            entity.RaiseOnNodeUpdated(trans, args);

            item.PersistenceState = PersistenceState.Persisted;
        }
예제 #2
0
        public override void Insert(OGM item)
        {
            Transaction trans  = Transaction.RunningTransaction;
            Entity      entity = item.GetEntity();

            string labels = string.Join(":", entity.GetBaseTypesAndSelf().Where(x => x.IsVirtual == false).Select(x => x.Label.Name));

            if (entity.RowVersion != null)
            {
                item.SetRowVersion(trans.TransactionDate);
            }

            IDictionary <string, object?> node = item.GetData();

            string create = string.Format("CREATE (inserted:{0} {{node}}) Return inserted", labels);

            if (entity.FunctionalId != null)
            {
                object?key = item.GetKey();
                if (key is null)
                {
                    string nextKey = string.Format("CALL blueprint41.functionalid.next('{0}') YIELD value as key", entity.FunctionalId.Label);
                    if (entity.FunctionalId.Format == IdFormat.Numeric)
                    {
                        nextKey = string.Format("CALL blueprint41.functionalid.nextNumeric('{0}') YIELD value as key", entity.FunctionalId.Label);
                    }

                    create = nextKey + "\r\n" + string.Format("CREATE (inserted:{0} {{node}}) SET inserted.{1} = key Return inserted", labels, entity.Key.Name);

                    node.Remove(entity.Key.Name);
                }
                else
                {
                    entity.FunctionalId.SeenUid(key.ToString() !);
                }
            }

            Dictionary <string, object?> parameters = new Dictionary <string, object?>();

            parameters.Add("node", node);

            Dictionary <string, object?>?customState = null;
            var args = entity.RaiseOnNodeCreate(trans, item, create, parameters, ref customState);

            var       result = trans.Run(args.Cypher, args.Parameters);
            RawRecord record = result.FirstOrDefault();

            if (record == null)
            {
                throw new InvalidOperationException($"Due to an unexpected state of the neo4j transaction, it seems impossible to insert the {entity.Name} at this time.");
            }

            RawNode inserted = record["inserted"].As <RawNode>();

            args.Id     = inserted.Id;
            args.Labels = inserted.Labels;
            // HACK: To make it faster we do not copy/replicate the Dictionary here, but it means someone
            //       could be changing the INode content from within an event. Possibly dangerous, but
            //       turns out the Neo4j driver can deal with it ... for now ...
            args.Properties = (Dictionary <string, object?>)inserted.Properties;
            args            = entity.RaiseOnNodeCreated(trans, args, inserted.Id, inserted.Labels, (Dictionary <string, object?>)inserted.Properties);

            item.SetData(args.Properties !);
            item.PersistenceState = PersistenceState.Persisted;
            Transaction.RunningTransaction.Register(entity.Name, item, true);
        }