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; }
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); }