コード例 #1
0
ファイル: TikListMerge.cs プロジェクト: sstercan/tik4net
        /// <summary>
        /// Performs update operations on mikrotik router.
        /// Items which are present in 'expected' and are not present in 'original' will be created on mikrotik router.
        /// Items which are present in both 'expected' and 'original' will be compared and updated (if are different - see <see cref="Field"/>, <see cref="WithKey"/>).
        /// Items which are not present in 'expected' and are present in 'original' will be deleted from mikrotik router.
        /// </summary>
        /// <returns>List of final entities on mikrotik router after save operation.</returns>
        public IEnumerable <TEntity> Save()
        {
            //TODO ensure all fields set
            List <TEntity> result = new List <TEntity>();
            Dictionary <string, TEntity> expectedDict = _expected.ToDictionary(_keyExtractor);
            Dictionary <string, TEntity> originalDict = _original.ToDictionary(_keyExtractor);

            //Delete
            foreach (var originalEntityPair in originalDict.Reverse()) //delete from end to begining of the list (just for better show in WinBox)
            {
                if (!expectedDict.ContainsKey(originalEntityPair.Key)) //present in original + not present in expected => delete
                {
                    _connection.Delete(originalEntityPair.Value);
                }
            }

            //Insert+Update
            var mergedFieldNames = ResolveFieldsFieldNames().ToArray();

            foreach (var expectedEntityPair in expectedDict.Reverse()) //from last to first ( <= move is indexed as moveBeforeEntity)
            {
                TEntity originalEntity;
                TEntity resultEntity;
                if (originalDict.TryGetValue(expectedEntityPair.Key, out originalEntity))
                {                                                                     //Update //present in both expected and original => update or NOOP
                  //copy .id from original to expected & save
                    if (!EntityFieldEquals(originalEntity, expectedEntityPair.Value)) //modified
                    {
                        UpdateEntityFields(originalEntity, expectedEntityPair.Value);
                        _connection.Save(originalEntity, mergedFieldNames);
                    }
                    resultEntity = originalEntity;
                }
                else
                { //Insert //present in expected and not present in original => insert
                    _connection.Save(expectedEntityPair.Value, mergedFieldNames);
                    resultEntity = expectedEntityPair.Value;
                }

                //Move entity to the right position
                if (_metadata.IsOrdered)
                {
                    if (result.Count > 0) // last one in the list (first taken) should be just added/leavedOnPosition and the next should be moved before the one which was added immediatelly before <=> result[0]
                    {
                        //TODO: only if is in different position
                        _connection.Move(resultEntity, result[0]); //before lastly added entity (foreach in reversed order)
                    }
                }

                result.Insert(0, resultEntity); //foreach in reversed order => put as first in result list
            }

            return(result);
        }
コード例 #2
0
ファイル: TikListMerge.cs プロジェクト: wizd/tik4net
        private IEnumerable <TEntity> SaveInternal(bool simulateOnly, out int insertCnt, out int updateCnt, out int deleteCnt, out int moveCnt)
        {
            insertCnt = 0;
            updateCnt = 0;
            deleteCnt = 0;
            moveCnt   = 0;

            //TODO ensure all fields set
            List <TEntity> result = new List <TEntity>();
            Dictionary <string, TEntity> expectedDict = _expected.ToDictionaryEx(_keyExtractor);
            Dictionary <string, TEntity> originalDict = _original.ToDictionaryEx(_keyExtractor);
            int idx = 0;
            Dictionary <string, int> originalIndexes = _original.ToDictionaryEx(_keyExtractor, i => idx++);

            //Delete
            foreach (var originalEntityPair in originalDict.Reverse()) //delete from end to begining of the list (just for better show in WinBox)
            {
                if (!expectedDict.ContainsKey(originalEntityPair.Key)) //present in original + not present in expected => delete
                {
                    if (_filterCallback(MergeOperation.Delete, originalEntityPair.Value, default(TEntity)))
                    {
                        if (!simulateOnly)
                        {
                            LogDml(MergeOperation.Delete, originalEntityPair.Value, default(TEntity));
                            _connection.Delete(originalEntityPair.Value);
                        }
                        deleteCnt++;
                    }
                }
            }

            //Insert+Update
            var mergedFieldNames   = ResolveFieldsFieldNames().ToArray();
            var insertedFieldNames = ResolveJustForInsertFieldNames().ToArray();

            foreach (var expectedEntityPair in expectedDict.Reverse()) //from last to first ( <= move is indexed as moveBeforeEntity)
            {
                TEntity originalEntity;
                TEntity resultEntity;
                if (originalDict.TryGetValue(expectedEntityPair.Key, out originalEntity))
                {                                                                     //Update //present in both expected and original => update or NOOP
                  //copy .id from original to expected & save
                    if (!EntityFieldEquals(originalEntity, expectedEntityPair.Value)) //modified
                    {
                        if (_filterCallback(MergeOperation.Update, originalEntity, expectedEntityPair.Value))
                        {
                            if (!simulateOnly)
                            {
                                LogDml(MergeOperation.Update, originalEntity, expectedEntityPair.Value);
                                UpdateEntityFields(originalEntity, expectedEntityPair.Value);
                                _connection.Save(originalEntity, mergedFieldNames);
                            }
                            updateCnt++;
                        }
                    }
                    resultEntity = originalEntity;
                }
                else
                { //Insert //present in expected and not present in original => insert
                    if (_filterCallback(MergeOperation.Insert, default(TEntity), expectedEntityPair.Value))
                    {
                        if (!simulateOnly)
                        {
                            LogDml(MergeOperation.Insert, default(TEntity), expectedEntityPair.Value);
                            _connection.Save(expectedEntityPair.Value, mergedFieldNames.Concat(insertedFieldNames));
                        }
                        insertCnt++;
                    }
                    resultEntity = expectedEntityPair.Value;
                }

                //Move entity to the right position
                if (_metadata.IsOrdered)
                {
                    if (result.Count > 0) // last one in the list (first taken) should be just added/leavedOnPosition and the next should be moved before the one which was added immediatelly before <=> result[0]
                    {
                        // only if is in different position (is not after result[0])
                        int resultEntityIdx, previousEntityIdx = -1;
                        if (!originalIndexes.TryGetValue(_keyExtractor(resultEntity), out resultEntityIdx) ||
                            !originalIndexes.TryGetValue(_keyExtractor(result[0]), out previousEntityIdx) ||
                            resultEntityIdx != previousEntityIdx - 1)
                        {
                            if (!simulateOnly)
                            {
                                LogMove(resultEntity, resultEntityIdx, previousEntityIdx);
                                _connection.Move(resultEntity, result[0]); //before lastly added entity (foreach in reversed order)
                            }
                            moveCnt++;
                        }
                    }
                }

                result.Insert(0, resultEntity); //foreach in reversed order => put as first in result list
            }

            return(result);
        }