public override List <CdcTableTypeModel> ImportCdcData(string fromLsn = null, string toLsn = null)
 {
     return(GetCdcDataTable(fromLsn, toLsn).AsEnumerable().Select(row =>
     {
         try
         {
             var contentId = Convert.ToInt32(row[ContentItemColumnName.ContentId]);
             return new CdcTableTypeModel
             {
                 ChangeType = CdcActionType.Data,
                 Action = (CdcOperationType)Enum.Parse(typeof(CdcOperationType), Convert.ToString(row[CdcCommonConstants.Operation])),
                 TransactionDate = (DateTime)row[CdcCommonConstants.TransactionDate],
                 TransactionLsn = row[CdcCommonConstants.TransactionLsn] as string,
                 SequenceLsn = row[CdcCommonConstants.SequenceLsn] as string,
                 FromLsn = row[CdcCommonConstants.FromLsn] as string,
                 ToLsn = row[CdcCommonConstants.ToLsn] as string,
                 Entity = new CdcEntityModel
                 {
                     EntityType = TarantoolContentArticleModel.EntityType,
                     InvariantName = TarantoolContentArticleModel.GetInvariantName(contentId),
                     Columns = new Dictionary <string, object>
                     {
                         { TarantoolContentArticleModel.ContentItemId, Convert.ToInt32(row[ContentItemColumnName.ContentItemId]) },
                         { TarantoolContentArticleModel.StatusTypeId, Convert.ToInt32(row[ContentItemColumnName.StatusTypeId]) },
                         { TarantoolContentArticleModel.Visible, Convert.ToInt32(row[ContentItemColumnName.Visible]) == 1 },
                         { TarantoolContentArticleModel.Archive, Convert.ToInt32(row[ContentItemColumnName.Archive]) == 1 },
                         { TarantoolContentArticleModel.Created, (DateTime)row[ContentItemColumnName.Created] },
                         { TarantoolContentArticleModel.Modified, (DateTime)row[ContentItemColumnName.Modified] },
                         { TarantoolContentArticleModel.LastModifiedBy, Convert.ToInt32(row[ContentItemColumnName.LastModifiedBy]) }
                     },
                     MetaData = new Dictionary <string, object>
                     {
                         { TarantoolContentArticleModel.IsSplitted, Equals(true, row[ContentItemColumnName.Splitted]) }
                     }
                 }
             };
         }
         catch (Exception ex)
         {
             throw new Exception($"There was an exception for parsing \"{CaptureInstanceName}\" row: {row.ToSimpleDataRow().ToJsonLog()}", ex);
         }
     }).OrderBy(cdc => cdc.TransactionLsn).ToList());
 }
        private IEnumerable <CdcTableTypeModel> GetContentArticleDtoFilteredByNetChanges(string fromLsn = null, string toLsn = null)
        {
            var contentItemModel = ImportData(CdcCaptureConstants.ContentItem, fromLsn, toLsn);
            var contentDataModel = ImportData(CdcCaptureConstants.ContentData, fromLsn, toLsn);

            var filteredContentItemModel         = FilterByIsSplitted(contentItemModel);
            var contentItemsFilteredByNetChanges = filteredContentItemModel.GetCdcDataFilteredByLsnNetChanges(cim => new
            {
                contentItemId = cim.Entity.Columns[TarantoolContentArticleModel.ContentItemId].ToString(),
                isSplitted    = (bool)cim.Entity.MetaData[TarantoolContentArticleModel.IsSplitted],
                cim.TransactionLsn
            });

            var contentDataFilteredByNetChanges = contentDataModel.GetCdcDataFilteredByLsnNetChangesWithColumnsCopy(cdm => new
            {
                attributeId   = cdm.Entity.Columns[TarantoolContentArticleModel.AttributeId].ToString(),
                contentItemId = cdm.Entity.Columns[TarantoolContentArticleModel.ContentItemId].ToString(),
                isSplitted    = (bool)cdm.Entity.MetaData[TarantoolContentArticleModel.IsSplitted],
                cdm.TransactionLsn
            });

            var contentDataToItemLookup = contentDataFilteredByNetChanges.ToLookup(cdm => new
            {
                cdm.TransactionLsn,
                contentItemId = cdm.Entity.Columns[TarantoolContentArticleModel.ContentItemId],
                isSplitted    = cdm.Entity.MetaData[TarantoolContentArticleModel.IsSplitted]
            });

            return(contentItemsFilteredByNetChanges.AsParallel().Select(cim =>
            {
                var fieldColumns = contentDataToItemLookup[new
                                                           {
                                                               cim.TransactionLsn,
                                                               contentItemId = cim.Entity.Columns[TarantoolContentArticleModel.ContentItemId],
                                                               isSplitted = cim.Entity.MetaData[TarantoolContentArticleModel.IsSplitted]
                                                           }].OrderBy(cdm => cdm.SequenceLsn).Select(cdm => new KeyValuePair <string, object>(
                                                                                                         TarantoolContentArticleModel.GetFieldName(cdm.Entity.Columns[TarantoolContentArticleModel.AttributeId]),
                                                                                                         cdm.Entity.Columns[TarantoolContentArticleModel.Data])
                                                                                                     );

                cim.Entity.Columns.AddRange(fieldColumns);
                return cim;
            }));
        }