private void ResolveSourceKey(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { stateChange.SourceKey = stateChange.CurrentSyncState?.Key ?? stateChange.LastSyncState?.Key; Log.Debug($"{stateChange}"); }, nameof(ResolveSourceKey)); }
protected virtual List <StateChange <TEntityA, TEntityB> > GetStateChanges() { var result = new List <StateChange <TEntityA, TEntityB> >(); var currentStates = DataSource.GetStates().ToList(); var lastStates = SyncStateStorage.GetStates(Context).ToList(); foreach (var currentState in currentStates) { var lastState = lastStates.FirstOrDefault(x => x.Key == currentState.Key); if (lastState == null) { var insert = new StateChange <TEntityA, TEntityB> { CurrentSyncState = currentState }; result.Add(insert); Log.Debug( $"Theoretical INSERT: CurrentState = '{insert.CurrentSyncState}', LastState = '{insert.LastSyncState}'"); } else { if (lastState.Hash != currentState.Hash) { var update = new StateChange <TEntityA, TEntityB> { CurrentSyncState = currentState, LastSyncState = lastState }; result.Add(update); Log.Debug( $"Theoretical UPDATE: CurrentState = '{update.CurrentSyncState}', LastState = '{update.LastSyncState}'"); } } } foreach (var lastState in lastStates) { var currentState = currentStates.SingleOrDefault(x => x.Key == lastState.Key); if (currentState == null) { var delete = new StateChange <TEntityA, TEntityB> { LastSyncState = lastState }; result.Add(delete); Log.Debug( $"Theoretical DELETE: CurrentState = '{delete.CurrentSyncState}', LastState = '{delete.LastSyncState}'"); } } Log.Info($"Detected {result.Count} changes. Inserts: {result.Count(c => c.Operation == OperationEnum.Insert)}, Updates: {result.Count(c => c.Operation == OperationEnum.Update)}, Deletes: {result.Count(c => c.Operation == OperationEnum.Delete)}, Unknowns: {result.Count(c => c.Operation == OperationEnum.None)}"); return(result); }
private void LookupSourceItem(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { if (stateChange.SourceKey == null) { return; } stateChange.SourceItem = DataSource.GetByKey(stateChange.SourceKey); Log.Debug($"{stateChange}"); }, nameof(LookupSourceItem)); }
private void ResolveTargetKey(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { if (stateChange.SourceKey == null) { return; } stateChange.SyncKeyMap = SyncKeyMapStorage.GetBySourceKey(Context, stateChange.SourceKey); stateChange.TargetKey = stateChange.SyncKeyMap?.TargetKey; Log.Debug($"{stateChange}"); }, nameof(ResolveTargetKey)); }
private void LookupTargetItemFallback(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { if (stateChange.TargetItem != null) { return; } if (stateChange.SourceItem != null) { // lets try to get target item key by source item stateChange.TargetKey = DataTarget.GetKeyBySourceItem(stateChange.SourceItem); LookupTargetItem(stateChange); } Log.Debug($"{stateChange}"); }, nameof(LookupTargetItemFallback)); }
private void PerformDataOperation(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { Log.Debug($"Performing Data Operation ({stateChange.Operation}) on Entity: {stateChange}"); switch (stateChange.Operation) { case OperationEnum.Insert: stateChange.TargetKey = DataTarget.Insert(stateChange.SourceItem); Log.Debug( $"INSERT: SourceKey = '{stateChange.SourceKey}', TargetKey = '{stateChange.TargetKey}'"); ExecuteNestedTasks?.Invoke(stateChange.SourceKey, stateChange.TargetKey, stateChange.SourceItem, stateChange.TargetItem, stateChange); break; case OperationEnum.Update: stateChange.TargetKey = DataTarget.Update(stateChange.SourceItem, stateChange.TargetItem); Log.Debug( $"UPDATE: SourceKey = '{stateChange.SourceKey}', TargetKey = '{stateChange.TargetKey}'"); ExecuteNestedTasks?.Invoke(stateChange.SourceKey, stateChange.TargetKey, stateChange.SourceItem, stateChange.TargetItem, stateChange); break; case OperationEnum.Delete: Log.Debug( $"DELETE: SourceKey = '{stateChange.SourceKey}', TargetKey = '{stateChange.TargetKey}'"); ExecuteNestedTasks?.Invoke(stateChange.SourceKey, stateChange.TargetKey, stateChange.SourceItem, stateChange.TargetItem, stateChange); DataTarget.Delete(stateChange.TargetItem); stateChange.TargetKey = null; break; case OperationEnum.None: break; } }, nameof(PerformDataOperation)); }
private void DetectDataOperation(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { if ((stateChange.SourceItem != null) && (stateChange.TargetItem == null)) { stateChange.Operation = OperationEnum.Insert; return; } if ((stateChange.SourceItem != null) && (stateChange.TargetItem != null)) { stateChange.Operation = OperationEnum.Update; return; } if ((stateChange.SourceItem == null) && (stateChange.TargetItem != null)) { Log.Debug($"DELETE: TargetKey = '{stateChange.TargetKey}'"); stateChange.Operation = OperationEnum.Delete; } Log.Debug($"{stateChange}"); }, nameof(DetectDataOperation)); }
private void UpdateSyncState(StateChange <TEntityA, TEntityB> stateChange) { TimedAction(() => { switch (stateChange.Operation) { case OperationEnum.Insert: case OperationEnum.Update: if (stateChange.LastSyncState == null) { SyncStateStorage.Create(Context, stateChange.CurrentSyncState.Key, stateChange.CurrentSyncState.Hash); } else { var syncState = stateChange.LastSyncState; syncState.Context = Context; syncState.Hash = stateChange.CurrentSyncState.Hash; SyncStateStorage.Update(syncState); } break; case OperationEnum.None: case OperationEnum.Delete: if (stateChange.LastSyncState != null) { SyncStateStorage.Delete(stateChange.LastSyncState); } break; default: throw new ArgumentOutOfRangeException(); } Log.Debug($"{stateChange}"); }, nameof(UpdateSyncState)); }