public static void ReplaceObject(ObjectClass obj, Zetbox.API.IDataObject target, Zetbox.API.IDataObject source) { if (obj == null) throw new ArgumentNullException("obj"); if (target == null) throw new ArgumentNullException("target"); if (source == null) throw new ArgumentNullException("source"); var cls = _frozenCtx.FindPersistenceObject<ObjectClass>(obj.ExportGuid); var clsType = cls.GetDescribedInterfaceType(); if (clsType != _frozenCtx.GetInterfaceType(target) || clsType != _frozenCtx.GetInterfaceType(source)) { throw new ArgumentException("source and target must match the object class"); } Logging.Server.InfoFormat("ReplaceObject: target = {0} ({1}) - \"{2}\"; source = target = {3} ({4}) - \"{5}\"", target.GetType().Name, target.ID, target, source.GetType().Name, source.ID, source); var relEnds = _frozenCtx.GetQuery<RelationEnd>() .Where(i => i.Type == cls) .ToList(); using (var scope = _scopeFactory.BeginLifetimeScope()) using (var ctx = scope.Resolve<IZetboxServerContext>()) { var targetObj = ctx.FindPersistenceObject(clsType, target.ID); var sourceObj = ctx.FindPersistenceObject(clsType, source.ID); var sourceID = source.ID; foreach (var relEnd in relEnds) { var otherEnd = relEnd.Parent.GetOtherEnd(relEnd); var rel = relEnd.Parent; if (otherEnd.Navigator != null) { var prop = otherEnd.Navigator; var propName = prop.Name; var refClass = (ObjectClass)prop.ObjectClass; var ifType = refClass.GetDescribedInterfaceType(); if (prop.GetIsList()) { Logging.Server.DebugFormat("Replacing on list {0}", propName); foreach (var refObj in ctx.Internals().GetPersistenceObjectQuery(ifType).Where(string.Format("{0}.Any(ID == @0)", propName), sourceID)) { refObj.RemoveFromCollection(propName, sourceObj); refObj.AddToCollection(propName, targetObj, true); } } else { Logging.Server.DebugFormat("Replacing on property {0}", propName); foreach (var refObj in ctx.Internals().GetPersistenceObjectQuery(ifType).Where(string.Format("{0}.ID == @0", propName), sourceID)) { refObj.SetPropertyValue(propName, targetObj); } } } else { // Not my business // The only side that that mathers is the side, that POINTS to the object in question. } } ctx.Delete(sourceObj); ctx.SubmitChanges(); } }