/// <summary> /// Loads the snapshot package. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public string LoadSnapshotPackage(LoadPackageContext context) { var result = string.Empty; try { using (var snapshotObjectSpace = new ObjectSpace(context.Package.UnitOfWork)) { // create root context var sourceMaps = snapshotObjectSpace.GetObjects <SnapshotOidMap>(); var rootContext = new SnapshotLoadContext(context, sourceMaps); context.Worker.ReportProgress(string.Format(Localizer.ObjectsFoundInSnapshot, sourceMaps.Count)); // restore all of object from snapshot foreach (var sourceMap in sourceMaps) { loadSnapshotObject(rootContext, sourceMap); } // fix OidMap references var newMaps = from c in context.ObjectSpace.ModifiedObjects.Cast <object>() where c is OidMap && ((OidMap)c).NewObject != null select c as OidMap; context.ObjectSpace.CommitChanges(); newMaps.ToList().ForEach(x => x.FixReference()); snapshotPostLoad(context.ObjectSpace); restoreLastLoadedNum(context, snapshotObjectSpace); context.ObjectSpace.CommitChanges(); snapshotObjectSpace.Rollback(); } } catch (Exception exception) { result = string.Format(Localizer.SnapshotLoadingIsFailed, exception.Message); context.Worker.ReportError(result); } if (string.IsNullOrEmpty(result)) { if (context.Worker.CancellationPending) { result = Localizer.LoadingAborted; } context.Worker.ReportProgress(Color.Blue, Localizer.SnapshotLoadingIs, (context.Worker.CancellationPending ? Localizer.Aborted : Localizer.Finished)); } return(result); }
/// <summary> /// Loads the snapshot object. /// </summary> /// <param name="context">The context.</param> /// <param name="sourceMap">The source map.</param> /// <returns></returns> private object loadSnapshotObject(SnapshotLoadContext context, SnapshotOidMap sourceMap) { // look for existing object in app database var result = OidMap.FindApplicationObject(context.ObjectSpace, sourceMap, context.Package.SenderNodeId); // if not found then create new one if (result == null) { var typeInfo = context.ObjectSpace.TypesInfo.FindTypeInfo(sourceMap.Target.Target.GetType()); result = context.ObjectSpace.CreateObject(typeInfo.Type); } // register mapping updateObjectMapping(context, sourceMap, result); // restore object's state from snapshot restoreSnapshotObjectState(context, (IXPObject)sourceMap.Target.Target, (IXPObject)result); return(result); }
/// <summary> /// Updates the object mapping. /// </summary> /// <param name="context">The context.</param> /// <param name="sourceMap">The source map.</param> /// <param name="appObject">The app object.</param> private void updateObjectMapping(SnapshotLoadContext context, IPackageObjectReference sourceMap, object appObject) { if (context.UpdatedMapping.Contains(appObject)) { return; } context.UpdatedMapping.Add(appObject); foreach (var mappingStr in sourceMap.KnownMapping.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { var mapArray = mappingStr.Split('\a'); var nodeId = mapArray[0]; var objectId = mapArray[1]; var oidMap = OidMap.GetOidMap(appObject, nodeId); if (oidMap == null) { OidMap.CreateOidMap(context.ObjectSpace, objectId, nodeId, (IXPObject)appObject); } } }
/// <summary> /// Restores the state of the snapshot object. /// </summary> /// <param name="context">The context.</param> /// <param name="snapshotObject">The snapshot object.</param> /// <param name="appObject">The app object.</param> private void restoreSnapshotObjectState(SnapshotLoadContext context, IXPObject snapshotObject, IXPObject appObject) { if (context.RestoredObjects.Contains(snapshotObject)) { return; } context.RestoredObjects.Add(snapshotObject); var snapClassInfo = snapshotObject.ClassInfo; var modelClass = XafDeltaModule.XafApp.FindModelClass(snapClassInfo.ClassType); // restore non collection properties foreach (var snapMemberInfo in snapClassInfo.Members.Where(x => x.IsPersistent && !x.IsReadOnly && !(x is ServiceField) && !x.IsKey)) { // skip non snapshot members if (modelClass != null) { var modelMember = modelClass.FindMember(snapMemberInfo.Name); if (modelMember != null && modelMember.NonSnapshot()) { continue; } } var appMemberInfo = appObject.ClassInfo.GetMember(snapMemberInfo.Name); // skip unknown and readonly properties if (appMemberInfo == null || appMemberInfo.IsReadOnly) { continue; } // new value grom snapshot var snapValue = snapMemberInfo.GetValue(snapshotObject); var memberIsRestored = false; // XPO references if (snapMemberInfo.ReferenceType != null) { // aggregated objects if (snapMemberInfo.IsAggregated && snapValue != null) { // app current aggregate value var aggrObj = appMemberInfo.GetValue(appObject); // if aggregated object in app is not null // then link it to snapshot object and restore state if (aggrObj != null) { updateObjectMapping(context, context.Maps[snapValue], aggrObj); restoreSnapshotObjectState(context, (IXPObject)snapValue, (IXPObject)aggrObj); memberIsRestored = true; } } if (snapValue != null && !memberIsRestored) { var snapOidMap = context.Maps[snapValue]; appMemberInfo.SetValue(appObject, loadSnapshotObject(context, snapOidMap)); memberIsRestored = true; } } if (!memberIsRestored) { appMemberInfo.SetValue(appObject, snapValue); } } // restore collections state foreach (var snapMemberInfo in snapClassInfo.Members.Where(x => !x.Name.EndsWith("__Links") && (x.IsManyToMany || x.IsManyToManyAlias || x.IsCollection || x.IsAssociationList))) { // skip non snapshot members if (modelClass != null) { var modelMember = modelClass.FindMember(snapMemberInfo.Name); if (modelMember != null && modelMember.MemberInfo.FindAttribute <NonSnapshotAttribute>() != null) { continue; } } var snapCollection = snapMemberInfo.GetValue(snapshotObject) as IList; var appMemberInfo = appObject.ClassInfo.GetMember(snapMemberInfo.Name); var appCollection = appMemberInfo.GetValue(appObject) as IList; if (snapCollection != null && appCollection != null) { foreach (var snapElement in snapCollection) { if (context.Maps.ContainsKey(snapElement)) { var appElement = loadSnapshotObject(context, context.Maps[snapElement]); if (!appCollection.Contains(appElement)) { appCollection.Add(appElement); } } } } } }
/// <summary> /// Updates the object mapping. /// </summary> /// <param name="context">The context.</param> /// <param name="sourceMap">The source map.</param> /// <param name="appObject">The app object.</param> private void updateObjectMapping(SnapshotLoadContext context, IPackageObjectReference sourceMap, object appObject) { if(context.UpdatedMapping.Contains(appObject)) return; context.UpdatedMapping.Add(appObject); foreach (var mappingStr in sourceMap.KnownMapping.Split(new[]{'\n'}, StringSplitOptions.RemoveEmptyEntries)) { var mapArray = mappingStr.Split('\a'); var nodeId = mapArray[0]; var objectId = mapArray[1]; var oidMap = OidMap.GetOidMap(appObject, nodeId); if(oidMap == null) OidMap.CreateOidMap(context.ObjectSpace, objectId, nodeId, (IXPObject)appObject); } }
/// <summary> /// Restores the state of the snapshot object. /// </summary> /// <param name="context">The context.</param> /// <param name="snapshotObject">The snapshot object.</param> /// <param name="appObject">The app object.</param> private void restoreSnapshotObjectState(SnapshotLoadContext context, IXPObject snapshotObject, IXPObject appObject) { if(context.RestoredObjects.Contains(snapshotObject)) return; context.RestoredObjects.Add(snapshotObject); var snapClassInfo = snapshotObject.ClassInfo; var modelClass = XafDeltaModule.XafApp.FindModelClass(snapClassInfo.ClassType); // restore non collection properties foreach (var snapMemberInfo in snapClassInfo.Members.Where(x => x.IsPersistent && !x.IsReadOnly && !(x is ServiceField) && !x.IsKey)) { // skip non snapshot members if(modelClass != null) { var modelMember = modelClass.FindMember(snapMemberInfo.Name); if (modelMember != null && modelMember.NonSnapshot()) continue; } var appMemberInfo = appObject.ClassInfo.GetMember(snapMemberInfo.Name); // skip unknown and readonly properties if(appMemberInfo == null || appMemberInfo.IsReadOnly) continue; // new value grom snapshot var snapValue = snapMemberInfo.GetValue(snapshotObject); var memberIsRestored = false; // XPO references if (snapMemberInfo.ReferenceType != null) { // aggregated objects if (snapMemberInfo.IsAggregated && snapValue != null) { // app current aggregate value var aggrObj = appMemberInfo.GetValue(appObject); // if aggregated object in app is not null // then link it to snapshot object and restore state if (aggrObj != null) { updateObjectMapping(context, context.Maps[snapValue], aggrObj); restoreSnapshotObjectState(context, (IXPObject)snapValue, (IXPObject)aggrObj); memberIsRestored = true; } } if (snapValue != null && !memberIsRestored) { var snapOidMap = context.Maps[snapValue]; appMemberInfo.SetValue(appObject, loadSnapshotObject(context, snapOidMap)); memberIsRestored = true; } } if (!memberIsRestored) appMemberInfo.SetValue(appObject, snapValue); } // restore collections state foreach (var snapMemberInfo in snapClassInfo.Members.Where(x => !x.Name.EndsWith("__Links") && (x.IsManyToMany || x.IsManyToManyAlias || x.IsCollection || x.IsAssociationList))) { // skip non snapshot members if (modelClass != null) { var modelMember = modelClass.FindMember(snapMemberInfo.Name); if (modelMember != null && modelMember.MemberInfo.FindAttribute<NonSnapshotAttribute>() != null) continue; } var snapCollection = snapMemberInfo.GetValue(snapshotObject) as IList; var appMemberInfo = appObject.ClassInfo.GetMember(snapMemberInfo.Name); var appCollection = appMemberInfo.GetValue(appObject) as IList; if (snapCollection != null && appCollection != null) foreach (var snapElement in snapCollection) { if (context.Maps.ContainsKey(snapElement)) { var appElement = loadSnapshotObject(context, context.Maps[snapElement]); if (!appCollection.Contains(appElement)) appCollection.Add(appElement); } } } }
/// <summary> /// Loads the snapshot object. /// </summary> /// <param name="context">The context.</param> /// <param name="sourceMap">The source map.</param> /// <returns></returns> private object loadSnapshotObject(SnapshotLoadContext context, SnapshotOidMap sourceMap) { // look for existing object in app database var result = OidMap.FindApplicationObject(context.ObjectSpace, sourceMap, context.Package.SenderNodeId); // if not found then create new one if(result == null) { var typeInfo = context.ObjectSpace.TypesInfo.FindTypeInfo(sourceMap.Target.Target.GetType()); result = context.ObjectSpace.CreateObject(typeInfo.Type); } // register mapping updateObjectMapping(context, sourceMap, result); // restore object's state from snapshot restoreSnapshotObjectState(context, (IXPObject)sourceMap.Target.Target, (IXPObject)result); return result; }
/// <summary> /// Loads the snapshot package. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public string LoadSnapshotPackage(LoadPackageContext context) { var result = string.Empty; try { using (var snapshotObjectSpace = new ObjectSpace(context.Package.UnitOfWork)) { // create root context var sourceMaps = snapshotObjectSpace.GetObjects<SnapshotOidMap>(); var rootContext = new SnapshotLoadContext(context, sourceMaps); context.Worker.ReportProgress(string.Format(Localizer.ObjectsFoundInSnapshot, sourceMaps.Count)); // restore all of object from snapshot foreach (var sourceMap in sourceMaps) loadSnapshotObject(rootContext, sourceMap); // fix OidMap references var newMaps = from c in context.ObjectSpace.ModifiedObjects.Cast<object>() where c is OidMap && ((OidMap)c).NewObject != null select c as OidMap; context.ObjectSpace.CommitChanges(); newMaps.ToList().ForEach(x => x.FixReference()); snapshotPostLoad(context.ObjectSpace); restoreLastLoadedNum(context, snapshotObjectSpace); context.ObjectSpace.CommitChanges(); snapshotObjectSpace.Rollback(); } } catch (Exception exception) { result = string.Format(Localizer.SnapshotLoadingIsFailed, exception.Message); context.Worker.ReportError( result); } if (string.IsNullOrEmpty(result)) { if (context.Worker.CancellationPending) result = Localizer.LoadingAborted; context.Worker.ReportProgress(Color.Blue, Localizer.SnapshotLoadingIs, (context.Worker.CancellationPending ? Localizer.Aborted : Localizer.Finished)); } return result; }