public UpdateDefinition <BsonDocument> BuildUpdatesForSave(UpdateDefinition <BsonDocument> update,
                                                                   TrackableDictionaryTracker <TKey, TValue> tracker,
                                                                   params object[] keyValues)
        {
            var keyNamespace = DocumentHelper.ToDotPathWithTrailer(keyValues);

            foreach (var change in tracker.ChangeMap)
            {
                switch (change.Value.Operation)
                {
                case TrackableDictionaryOperation.Add:
                case TrackableDictionaryOperation.Modify:
                    update = update == null
                                     ? Builders <BsonDocument> .Update.Set(keyNamespace + change.Key,
                                                                           change.Value.NewValue)
                                     : update.Set(keyNamespace + change.Key, change.Value.NewValue);

                    break;

                case TrackableDictionaryOperation.Remove:
                    update = update == null
                                     ? Builders <BsonDocument> .Update.Unset(keyNamespace + change.Key)
                                     : update.Unset(keyNamespace + change.Key);

                    break;
                }
            }
            return(update);
        }
        public static TrackableDictionaryTracker <TKey, TValue> Deserialize(ref MessagePackReader reader,
                                                                            MessagePackSerializerOptions options)
        {
            var count = reader.ReadArrayHeader();
            TrackableDictionaryTracker <TKey, TValue> tracker = new TrackableDictionaryTracker <TKey, TValue>();

            for (var i = 0; i < count; i++)
            {
                var operation = reader.ReadInt32();
                var key       = MessagePackSerializer.Deserialize <TKey>(ref reader, options);
                var value     = MessagePackSerializer.Deserialize <TValue>(ref reader, options);
                switch (operation)
                {
                case (int)TrackableDictionaryOperation.Add:
                    tracker.TrackAdd(key, value);
                    break;

                case (int)TrackableDictionaryOperation.Remove:
                    tracker.TrackRemove(key, value);
                    break;

                case (int)TrackableDictionaryOperation.Modify:
                    tracker.TrackModify(key, default(TValue), value);
                    break;
                }
            }

            return(tracker);
        }
Beispiel #3
0
        public void TestDictionary_RollbackToTracker_Work()
        {
            var dict = CreateTestDictionaryWithTracker();

            dict[1] = "OneModified";
            dict.Remove(2);
            dict[4] = "FourAdded";

            var tracker2 = new TrackableDictionaryTracker <int, string>();

            dict.Tracker.ApplyTo(tracker2);
            dict.Tracker.RollbackTo(tracker2);

            var dict2 = CreateTestDictionary();

            tracker2.ApplyTo(dict2);

            Assert.Equal(
                new KeyValuePair <int, string>[]
            {
                new KeyValuePair <int, string>(1, "One"),
                new KeyValuePair <int, string>(2, "Two"),
                new KeyValuePair <int, string>(3, "Three")
            },
                dict2.OrderBy(kv => kv.Key));
        }
        public static void Serialize(ref MessagePackWriter writer, TrackableDictionaryTracker <TKey, TValue> value,
                                     MessagePackSerializerOptions options)
        {
            var tracker = value;

            writer.WriteArrayHeader(tracker.ChangeMap.Count);
            foreach (var item in tracker.ChangeMap)
            {
                switch (item.Value.Operation)
                {
                case TrackableDictionaryOperation.Add:
                    writer.Write((int)item.Value.Operation);
                    MessagePackSerializer.Serialize(ref writer, item.Key, options);
                    MessagePackSerializer.Serialize(ref writer, item.Value.NewValue, options);
                    break;

                case TrackableDictionaryOperation.Remove:
                    writer.Write((int)item.Value.Operation);
                    MessagePackSerializer.Serialize(ref writer, item.Key, options);
                    MessagePackSerializer.Serialize(ref writer, default(TValue), options);
                    break;

                case TrackableDictionaryOperation.Modify:
                    writer.Write((int)item.Value.Operation);
                    MessagePackSerializer.Serialize(ref writer, item.Key, options);
                    MessagePackSerializer.Serialize(ref writer, item.Value.NewValue, options);
                    break;
                }
            }
        }
        public void Test_DictionaryTracker_Serialize()
        {
            var tracker = new TrackableDictionaryTracker <int, string>();

            tracker.TrackAdd(1, "One");
            AssertTrackerSerialize(tracker);
        }
        public async Task <int> SaveAsync(DbConnection connection, TrackableDictionaryTracker <TKey, TValue> tracker,
                                          params object[] keyValues)
        {
            if (tracker.HasChange == false)
            {
                return(0);
            }

            var sql = BuildSqlForSave(tracker, keyValues);

            using (var command = _sqlProvider.CreateDbCommand(sql, connection))
            {
                return(await command.ExecuteNonQueryAsync());
            }
        }
Beispiel #7
0
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                                        JsonSerializer serializer)
        {
            if (reader.TokenType != JsonToken.StartObject)
            {
                return(null);
            }

            var tracker = new TrackableDictionaryTracker <TKey, TValue>();

            reader.Read();
            while (true)
            {
                if (reader.TokenType != JsonToken.PropertyName)
                {
                    break;
                }

                var str = (string)reader.Value;
                reader.Read();

                var    key = JsonConvert.DeserializeObject <TKey>(str.Substring(1));
                TValue obj;
                switch (str[0])
                {
                case '+':
                    obj = serializer.Deserialize <TValue>(reader);
                    reader.Read();
                    tracker.TrackAdd(key, obj);
                    break;

                case '-':
                    reader.Read();
                    tracker.TrackRemove(key, default(TValue));
                    break;

                case '=':
                    obj = serializer.Deserialize <TValue>(reader);
                    reader.Read();
                    tracker.TrackModify(key, default(TValue), obj);
                    break;
                }
            }

            return(tracker);
        }
        public async Task SaveAsync(IDatabase db, TrackableDictionaryTracker <TKey, TValue> tracker, RedisKey key)
        {
            var updates = tracker.ChangeMap.Where(i => i.Value.Operation == TrackableDictionaryOperation.Add ||
                                                  i.Value.Operation == TrackableDictionaryOperation.Modify)
                          .Select(i => new HashEntry(_keyToRedisValue(i.Key),
                                                     _valueToRedisValue(i.Value.NewValue))).ToArray();

            var removeKeys = tracker.RemoveKeys.Select(_keyToRedisValue).ToArray();

            if (updates.Length > 0)
            {
                await db.HashSetAsync(key, updates);
            }

            if (removeKeys.Length > 0)
            {
                await db.HashDeleteAsync(key, removeKeys);
            }
        }
Beispiel #9
0
        public static TrackableDictionaryTrackerSurrogate <TKey, TValue> Convert(
            TrackableDictionaryTracker <TKey, TValue> tracker)
        {
            if (tracker == null)
            {
                return(null);
            }

            var surrogate = new TrackableDictionaryTrackerSurrogate <TKey, TValue>();

            foreach (var item in tracker.ChangeMap)
            {
                surrogate.ChangeList.Add(new Change
                {
                    Operation = item.Value.Operation,
                    Key       = item.Key,
                    NewValue  = item.Value.NewValue,
                });
            }
            return(surrogate);
        }
        public Task <UpdateResult> SaveAsync(IMongoCollection <BsonDocument> collection,
                                             TrackableDictionaryTracker <TKey, TValue> tracker,
                                             params object[] keyValues)
        {
            if (keyValues.Length == 0)
            {
                throw new ArgumentException("At least 1 keyValue required.");
            }

            if (tracker.HasChange == false)
            {
                return(Task.FromResult((UpdateResult)null));
            }

            return(collection.UpdateOneAsync(
                       Builders <BsonDocument> .Filter.Eq("_id", keyValues[0]),
                       BuildUpdatesForSave(null, tracker, keyValues.Skip(1).ToArray()),
                       new UpdateOptions {
                IsUpsert = true
            }));
        }
Beispiel #11
0
        public static TrackableDictionaryTracker <TKey, TValue> Convert(
            TrackableDictionaryTrackerSurrogate <TKey, TValue> surrogate)
        {
            if (surrogate == null)
            {
                return(null);
            }

            var tracker = new TrackableDictionaryTracker <TKey, TValue>();

            foreach (var change in surrogate.ChangeList)
            {
                tracker.ChangeMap.Add(
                    change.Key,
                    new TrackableDictionaryTracker <TKey, TValue> .Change
                {
                    Operation = change.Operation,
                    NewValue  = change.NewValue
                });
            }
            return(tracker);
        }
 public void Serialize(ref MessagePackWriter writer, TrackableDictionaryTracker <TKey, TValue> value, MessagePackSerializerOptions options)
 {
     TrackableDictionaryTrackerMessagePackFormatter <TKey, TValue> .Serialize(ref writer, value, options);
 }
        public string BuildSqlForSave(TrackableDictionaryTracker <TKey, TValue> tracker,
                                      params object[] keyValues)
        {
            if (keyValues.Length != _headKeyColumns.Length)
            {
                throw new ArgumentException("Number of keyValues should be same with the number of head columns");
            }

            var sqlAdd    = new StringBuilder();
            var sqlModify = new StringBuilder();
            var removeIds = new List <TKey>();

            // generate sql command for each changes

            var insertCount = 0;

            foreach (var i in tracker.ChangeMap)
            {
                var v = i.Value.NewValue;
                switch (i.Value.Operation)
                {
                case TrackableDictionaryOperation.Add:
                    if (insertCount == 0)
                    {
                        sqlAdd.Append("INSERT INTO ").Append(_tableEscapedName);
                        sqlAdd.Append(" (").Append(_allColumnString).Append(") VALUES\n");
                    }
                    else
                    {
                        sqlAdd.Append(",\n");
                    }

                    sqlAdd.Append(" (");
                    for (var k = 0; k < _headKeyColumns.Length; k++)
                    {
                        sqlAdd.Append(_headKeyColumns[k].ConvertToSqlValue(keyValues[k]));
                        sqlAdd.Append(",");
                    }
                    sqlAdd.Append(_keyColumn.ConvertToSqlValue(i.Key));

                    foreach (var col in _valueColumns)
                    {
                        sqlAdd.Append(",").Append(col.ExtractToSqlValue(v));
                    }

                    sqlAdd.Append(")");

                    insertCount += 1;
                    if (insertCount >= 1000)
                    {
                        sqlAdd.Append(";\n");
                        insertCount = 0;
                    }
                    break;

                case TrackableDictionaryOperation.Modify:
                    sqlModify.Append("UPDATE ").Append(_tableEscapedName);
                    sqlModify.Append(" SET ");
                    var concating = false;
                    foreach (var col in _valueColumns)
                    {
                        if (concating == false)
                        {
                            concating = true;
                        }
                        else
                        {
                            sqlModify.Append(",");
                        }
                        sqlModify.Append(col.EscapedName).Append("=").Append(col.ExtractToSqlValue(v));
                    }

                    sqlModify.Append(" WHERE ");
                    for (var k = 0; k < _headKeyColumns.Length; k++)
                    {
                        sqlModify.Append(_headKeyColumns[k].EscapedName).Append("=");
                        sqlModify.Append(_headKeyColumns[k].ConvertToSqlValue(keyValues[k]));
                        sqlModify.Append(" AND ");
                    }

                    sqlModify.Append(_keyColumn.EscapedName).Append("=");
                    sqlModify.Append(_keyColumn.ConvertToSqlValue(i.Key)).Append(";\n");
                    break;

                case TrackableDictionaryOperation.Remove:
                    removeIds.Add(i.Key);
                    break;
                }
            }
            if (insertCount > 0)
            {
                sqlAdd.Append(";\n");
            }

            // merge insert, update and delete sql into one sql

            var sql = new StringBuilder();

            sql.Append(sqlAdd);
            sql.Append(sqlModify);
            if (removeIds.Any())
            {
                sql.Append("DELETE FROM ").Append(_tableEscapedName).Append(" WHERE ");
                for (var k = 0; k < _headKeyColumns.Length; k++)
                {
                    sql.Append(_headKeyColumns[k].EscapedName).Append("=");
                    sql.Append(_headKeyColumns[k].ConvertToSqlValue(keyValues[k]));
                    sql.Append(" AND ");
                }
                sql.Append(_keyColumn.EscapedName).Append(" IN (");
                var concating = false;
                foreach (var id in removeIds)
                {
                    if (concating == false)
                    {
                        concating = true;
                    }
                    else
                    {
                        sql.Append(",");
                    }
                    sql.Append(_keyColumn.ConvertToSqlValue(id));
                }
                sql.Append(");\n");
            }

            return(sql.ToString());
        }
        public void TestDictionary_RollbackToTracker_Work()
        {
            var dict = CreateTestDictionaryWithTracker();
            dict[1] = "OneModified";
            dict.Remove(2);
            dict[4] = "FourAdded";

            var tracker2 = new TrackableDictionaryTracker<int, string>();
            dict.Tracker.ApplyTo(tracker2);
            dict.Tracker.RollbackTo(tracker2);

            var dict2 = CreateTestDictionary();
            tracker2.ApplyTo(dict2);

            Assert.Equal(
                new KeyValuePair<int, string>[]
                {
                    new KeyValuePair<int, string>(1, "One"),
                    new KeyValuePair<int, string>(2, "Two"),
                    new KeyValuePair<int, string>(3, "Three")
                },
                dict2.OrderBy(kv => kv.Key));
        }