public static ExchangeData BiserDecode(byte[] enc = null, Biser.Decoder extDecoder = null)
        {
            Biser.Decoder decoder = null;
            if (extDecoder == null)
            {
                if (enc == null || enc.Length == 0)
                {
                    return(null);
                }
                decoder = new Biser.Decoder(enc);
            }
            else
            {
                if (extDecoder.CheckNull())
                {
                    return(null);
                }
                else
                {
                    decoder = extDecoder;
                }
            }

            ExchangeData m = new ExchangeData();



            m.LastServerSyncTimeStamp = decoder.GetLong();
            m.SyncOperations          = decoder.CheckNull() ? null : new System.Collections.Generic.List <SyncOperation>();
            if (m.SyncOperations != null)
            {
                decoder.GetCollection(() => {
                    var pvar1 = SyncOperation.BiserDecode(null, decoder);
                    return(pvar1);
                }, m.SyncOperations, true);
            }
            m.RepeatSynchro          = decoder.GetBool();
            m.NewServerSyncTimeStamp = decoder.GetLong();


            return(m);
        }
        public static SyncOperation BiserDecode(byte[] enc = null, Biser.Decoder extDecoder = null)
        {
            Biser.Decoder decoder = null;
            if (extDecoder == null)
            {
                if (enc == null || enc.Length == 0)
                {
                    return(null);
                }
                decoder = new Biser.Decoder(enc);
            }
            else
            {
                if (extDecoder.CheckNull())
                {
                    return(null);
                }
                else
                {
                    decoder = extDecoder;
                }
            }

            SyncOperation m = new SyncOperation();



            m.SyncTimestamp    = decoder.GetLong();
            m.SerializedObject = decoder.GetByteArray();
            m.Operation        = (eOperation)decoder.GetInt();
            m.Type             = decoder.GetString();
            m.InternalId       = decoder.GetLong();
            m.ExternalId       = decoder.GetLong();


            return(m);
        }
        public override List <SyncOperation> GetSyncOperations(DBreeze.Transactions.Transaction tran, out bool repeatSync)
        {
            var syncList = new List <SyncOperation>();

            _newLocalSyncTimeStamp = DateTime.UtcNow.Ticks; //This value will be applied if there is nothing to synchronize
            repeatSync             = false;

            var changedEntities = new Dictionary <long, Tuple <long, bool> >();    //Key is entityId, Value is Synctimestamp
            var entityType      = typeof(T).FullName;

            var lastLocalSyncTimeStamp = tran.Select <byte[], long>(_entitySync.entityTable, new byte[] { LocalSyncTS, 1 }).Value;

            foreach (var row in
                     tran.SelectForwardFromTo <byte[], byte[]>(_entitySync.entityTable,
                                                               new byte[] { SyncLog }.ConcatMany((lastLocalSyncTimeStamp + 1).To_8_bytes_array_BigEndian(), long.MinValue.To_8_bytes_array_BigEndian()),
                                                               true, //true, but LastLocalSyncTimeStamp+1 is used
                                                               new byte[] { SyncLog }.ConcatMany(long.MaxValue.To_8_bytes_array_BigEndian(), long.MaxValue.To_8_bytes_array_BigEndian()),
                                                               true))
            {
                if (changedEntities.Count > _entitySync.LimitationOfEntitesPerRound)
                {
                    repeatSync = true;
                    break;
                }

                //We will leave only last update of the particular entity
                if (!changedEntities.TryGetValue(row.Key.Substring(9, 8).To_Int64_BigEndian(), out var tpl1))
                {
                    changedEntities[row.Key.Substring(9, 8).To_Int64_BigEndian()] = new Tuple <long, bool>(row.Key.Substring(1, 8).To_Int64_BigEndian(),
                                                                                                           (row.Value?.Length >= 1 && row.Value[0] == 1) ? true : false) //indicating that new entity was inserted
                    ;
                }
                else
                {
                    changedEntities[row.Key.Substring(9, 8).To_Int64_BigEndian()] = new Tuple <long, bool>(row.Key.Substring(1, 8).To_Int64_BigEndian(),
                                                                                                           (tpl1.Item2 || (row.Value?.Length >= 1 && row.Value[0] == 1)) ? true : false) //indicating that new entity was inserted (from any of inserts that must be done for the id)
                    ;
                }

                _newLocalSyncTimeStamp = row.Key.Substring(1, 8).To_Int64_BigEndian();
            }

            foreach (var ent in changedEntities.OrderBy(r => r.Key))
            {
                var rowEntity = tran.Select <byte[], byte[]>(_entitySync.entityTable, new byte[] { Entity }.Concat(ent.Key.To_8_bytes_array_BigEndian()));

                var syncOperation = new SyncOperation()
                {
                    ExternalId    = ent.Value.Item2 ? 0 : ent.Key, //if entity new ExternalId will be 0 otherwise will equal to InternalId and higher than 0
                    InternalId    = ent.Key,
                    Operation     = rowEntity.Exists ? SyncOperation.eOperation.INSERT : SyncOperation.eOperation.REMOVE,
                    Type          = entityType,
                    SyncTimestamp = ent.Value.Item1
                };
                if (rowEntity.Exists)
                {
                    syncOperation.SerializedObject = rowEntity.GetDataBlockWithFixedAddress <byte[]>();
                }
                syncList.Add(syncOperation);
            }
            return(syncList);
        }