public void AttachDeletedObject(string typeName, string id)
        {
            var syncStatusContext = CreateSyncStatusContext();
            var syncObj           = AddOrCreateNewSyncObject(syncStatusContext, typeName, id);

            syncObj.IsDeleted  = true;
            syncObj.LastChange = DateTimeOffset.UtcNow;

            var updatedResult     = new UpdatedDataBatch();
            var updatedResultItem = CreateDownloadResponseItemInfo(syncObj, ChangesForDeletedObject);

            updatedResult.Items.Add(updatedResultItem);
            OnDataUpdated(updatedResult);

            syncStatusContext.SaveChanges();
        }
        public void AttachObjects(IEnumerable <IRealmiusObjectServer> objects)
        {
            var syncStatusContext = CreateSyncStatusContext();

            var updatedResult = new UpdatedDataBatch();

            foreach (var obj in objects)
            {
                try
                {
                    AttachObject(obj, syncStatusContext, updatedResult);
                }
                catch (Exception e)
                {
                    Logger.Exception(e, $"Error attaching object {obj.MobilePrimaryKey}");
                }
            }

            OnDataUpdated(updatedResult);
            syncStatusContext.SaveChanges();
        }
        private void AttachObject(IRealmiusObjectServer obj, SyncStatusDbContext syncStatusContext, UpdatedDataBatch updatedResult)
        {
            var typeName = GetEfTypeName(obj);
            var syncObj  = AddOrCreateNewSyncObject(syncStatusContext, typeName, obj.MobilePrimaryKey);

            var current = JObject.FromObject(obj);
            var diff    = JsonHelper.GetJsonDiff(JObject.Parse(syncObj.FullObjectAsJson ?? "{}"), current);

            var dateTimeNow = GetDate();

            foreach (JProperty jProperty in diff.Properties())
            {
                syncObj.ColumnChangeDates[jProperty.Name] = dateTimeNow;
            }

            ProcessAndAddChanges(syncObj, obj, updatedResult, diff.ToString());
        }
 protected virtual void OnDataUpdated(UpdatedDataBatch e)
 {
     DataUpdated?.Invoke(this, e);
 }
        private void ProcessAndAddChanges(SyncStatusServerObject syncStatusObject, IRealmiusObjectServer obj, UpdatedDataBatch updatedResult, string changes)
        {
            Process(syncStatusObject, obj);
            var updatedResultItem = CreateDownloadResponseItemInfo(syncStatusObject, changes);

            updatedResult.Items.Add(updatedResultItem);
        }
        protected virtual int ProcessChanges()
        {
            if (!EnableSyncTracking)
            {
                return(base.SaveChanges());
            }
            if (_syncConfiguration == null)
            {
                throw new InvalidOperationException($"{nameof(ChangeTrackingDbContext)} was not initialized (_syncConfiguration is null)!");
            }

            int result;

            try
            {
                var syncStatusContext = CreateSyncStatusContext();

                var updatedResult = new UpdatedDataBatch();
                var dateTimeNow   = GetDate();

                var entries = ChangeTracker.Entries()
                              .Where(x => !(x.Entity is LogEntryBase))
                              .Where(e => e.State == EntityState.Modified ||
                                     e.State == EntityState.Added ||
                                     e.State == EntityState.Deleted
                                     ).Select(x => new EfEntityInfo
                {
                    ModifiedProperties = x.State == EntityState.Deleted ? new Dictionary <string, bool>() : x.CurrentValues.PropertyNames.ToDictionary(z => z, z => x.Property(z).IsModified),
                    Entity             = x.Entity,
                    CurrentValues      = x.State == EntityState.Deleted ? null : x.CurrentValues?.Clone(),
                    OriginalValues     = x.State == EntityState.Added ? null : x.OriginalValues?.Clone(),
                    State = x.State
                }).ToList();

                result = base.SaveChanges();

                if (EnableAudit)
                {
                    SaveLogs(entries);
                    base.SaveChanges();
                }

                foreach (var entity in entries)
                {
                    var typeName = GetEfTypeName(entity.Entity);
                    if (!_syncedTypes.ContainsKey(typeName))
                    {
                        continue;
                    }
                    var syncTypeInfo = _syncedTypes[typeName];

                    var    obj = (IRealmiusObjectServer)entity.Entity;
                    var    syncStatusObject = AddOrCreateNewSyncObject(syncStatusContext, typeName, obj.MobilePrimaryKey);
                    string changes;
                    if (entity.State == EntityState.Modified)
                    {
                        var serializedCurrent = SerializeObject(obj);

                        if (syncStatusObject != null && syncStatusObject.FullObjectAsJson == serializedCurrent)
                        {
                            changes = null;
                        }
                        else
                        {
                            var jsonDiff = JsonHelper.GetJsonDiffAsJObject(
                                syncStatusObject?.FullObjectAsJson ?? "{}",
                                serializedCurrent);

                            if (syncStatusObject != null)
                            {
                                foreach (var property in jsonDiff.Properties())
                                {
                                    var propName = property.Name;
                                    syncStatusObject.ColumnChangeDates[propName] = dateTimeNow;
                                }
                            }

                            changes = jsonDiff.ToString();
                        }
                        syncStatusObject.IsDeleted = false;
                    }
                    else if (entity.State == EntityState.Added)
                    {
                        changes = SerializeObject(obj);
                        var jObject = JObject.Parse(changes);

                        foreach (var propName in jObject.Properties().Select(x => x.Name))
                        {
                            syncStatusObject.ColumnChangeDates[propName] = dateTimeNow;
                        }
                        syncStatusObject.IsDeleted = false;
                        changes = jObject.ToString();
                    }
                    else if (entity.State == EntityState.Deleted)
                    {
                        syncStatusObject.IsDeleted = true;
                        changes = ChangesForDeletedObject;
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException($"Entity state '{entity.State}' is not supported");
                    }

                    if (changes != null)
                    {
                        ProcessAndAddChanges(syncStatusObject, obj, updatedResult, changes);
                    }
                }

                if (updatedResult.Items.Count > 0)
                {
                    syncStatusContext.SaveChanges();

                    OnDataUpdated(updatedResult);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return(result);
        }