private DocumentChange[] determineChanges(UpdateBatch batch)
        {
            var types = _operations.Select(x => x.Key).TopologicalSort(GetTypeDependencies);

            foreach (var type in types)
            {
                if (!_operations.ContainsKey(type))
                {
                    continue;
                }

                foreach (var operation in _operations[type])
                {
                    // No Virginia, I do not approve of this but I'm pulling all my hair
                    // out as is trying to make this work
                    if (operation is DocumentStorageOperation)
                    {
                        operation.As <DocumentStorageOperation>().Persist(batch, _tenant);
                    }
                    else
                    {
                        batch.Add(operation);
                    }
                }
            }

            writeEvents(batch);

            batch.Add(_ancillaryOperations);

            var changes = detectTrackerChanges();

            changes.GroupBy(x => x.DocumentType).Each(group =>
            {
                var upsert = _tenant.StorageFor(group.Key);

                group.Each(c => { upsert.RegisterUpdate(null, UpdateStyle.Upsert, batch, c.Document, c.Json); });
            });

            return(changes);
        }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="inserts"></param>
        /// <param name="updates"></param>
        /// <param name="deletes"></param>
        /// <param name="connection"></param>
        /// #UPLOAD 3
        public void Update(DataTable changes, SpConnection connection, out Collection <SyncConflict> errors)
        {
            errors = new Collection <SyncConflict>();

            if (changes == null)
            {
                throw new ArgumentNullException("changes");
            }

            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            int _batchSize    = 25;
            int segmentsCount = (int)Math.Round(Math.Ceiling((double)changes.Rows.Count / _batchSize), 0);


            if (IgnoreColumnsOnUpdate != null)
            {
                // case to be handled
                // cannot remove Sharepoint ID.
                // cannot remove Primary Key of DataTable?

                foreach (string ignoredColumn in IgnoreColumnsOnUpdate)
                {
                    string clientColumn = GetClientColumnFromServerColumn(ignoredColumn);
                    if (clientColumn != null &&
                        changes.Columns.Contains(clientColumn))
                    {
                        changes.Columns.Remove(clientColumn);
                    }
                }
            }


            DataTable changesTotal = changes.Copy();

            for (int i = 0; i < segmentsCount; i++)
            {
                changes.Rows.Clear();

                CopyRows(changesTotal, changes, i * _batchSize, _batchSize);

                //SEND SEGMENT
                UpdateBatch batch = new UpdateBatch();

                string clientIdColumn = GetClientColumnFromServerColumn("ID");

                if (!changes.Columns.Contains(clientIdColumn))
                {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ColumnIDNotContained, clientIdColumn));
                }

                IDictionary <int, DataRow> IdMapping = new Dictionary <int, DataRow>();

                foreach (DataRow row in changes.Rows)
                {
                    UpdateItem u = batch.CreateNewItem();

                    switch (row.RowState)
                    {
                    case DataRowState.Added:
                        u.Command = UpdateCommands.Insert;
                        break;

                    case DataRowState.Deleted:
                        u.Command = UpdateCommands.Delete;
                        break;

                    case DataRowState.Modified:
                        u.Command = UpdateCommands.Update;
                        break;

                    case DataRowState.Unchanged:
                        continue;
                    }

                    if (u.Command == UpdateCommands.Delete)
                    {
                        row.RejectChanges();
                    }

                    if (u.Command != UpdateCommands.Insert)
                    {
                        if (!(row[clientIdColumn] is DBNull))
                        {
                            u.ListItemID = (int)row[clientIdColumn];
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (u.Command != UpdateCommands.Delete)
                    {
                        ListItem  item = new ListItem();
                        Exception e;

                        MapDataRowToListItem(row, item, out e);
                        u.ChangedItemData = item;
                        if (e != null && SyncTracer.IsErrorEnabled())
                        {
                            SyncTracer.Error(e.ToString());
                        }
                    }

                    batch.Add(u);
                    IdMapping[u.ID] = row;

                    if (u.Command == UpdateCommands.Delete)
                    {
                        row.Delete();
                    }
                }

                if (batch.Count != 0)
                {
                    //try
                    //{
                    UpdateResults results = connection.UpdateListItems(this.ListName, batch);
                    // FIX: errors must be handled appropriately
                    foreach (UpdateResult r in results)
                    {
                        if (!r.IsSuccess())
                        {
                            if (!IdMapping.ContainsKey(r.UpdateItemID))
                            {
                                throw new InvalidOperationException(
                                          String.Format(CultureInfo.CurrentCulture, Messages.NoIDMapping, r.UpdateItemID));
                            }

                            DataRow clientRow = IdMapping[r.UpdateItemID];
                            errors.Add(CreateSyncError(r, clientRow));
                        }
                    }
                    //}
                    //catch (Exception ex)
                    //{
                    ////usually connection error
                    //    foreach (UpdateItem item in batch)
                    //    {
                    //        if (!IdMapping.ContainsKey(item.ID))
                    //            throw new InvalidOperationException(
                    //                String.Format(CultureInfo.CurrentCulture, Messages.NoIDMapping, r.UpdateItemID));

                    //        DataRow clientRow = IdMapping[item.ID];
                    //        errors.Add(CreateSyncError(new UpdateResult(, clientRow));
                    //    }
                    //}
                }
                //END SEND SEGMENT
            }

            if (errors.Count == 0)
            {
                errors = null;
            }
        }
Exemple #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inserts"></param>
        /// <param name="updates"></param>
        /// <param name="deletes"></param>
        /// <param name="connection"></param>
        /// #UPLOAD 3
        public void Update(DataTable changes, SpConnection connection, out Collection<SyncConflict> errors)
        {
            errors = new Collection<SyncConflict>();

            if (changes == null)
                throw new ArgumentNullException("changes");

            if (connection == null)
                throw new ArgumentNullException("connection");

            int _batchSize = 25;
            int segmentsCount = (int)Math.Round( Math.Ceiling((double)changes.Rows.Count/ _batchSize),0);

            if (IgnoreColumnsOnUpdate != null)
            {
                // case to be handled
                // cannot remove Sharepoint ID.
                // cannot remove Primary Key of DataTable?

                foreach (string ignoredColumn in IgnoreColumnsOnUpdate)
                {
                    string clientColumn = GetClientColumnFromServerColumn(ignoredColumn);
                    if (clientColumn != null &&
                        changes.Columns.Contains(clientColumn))
                    {
                        changes.Columns.Remove(clientColumn);
                    }
                }
            }

            DataTable changesTotal = changes.Copy();

            for (int i = 0; i < segmentsCount; i++)
            {
                changes.Rows.Clear();

                CopyRows(changesTotal, changes, i * _batchSize, _batchSize);

                //SEND SEGMENT
                UpdateBatch batch = new UpdateBatch();

                string clientIdColumn = GetClientColumnFromServerColumn("ID");

                if (!changes.Columns.Contains(clientIdColumn))
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ColumnIDNotContained, clientIdColumn));

                IDictionary<int, DataRow> IdMapping = new Dictionary<int, DataRow>();

                foreach (DataRow row in changes.Rows)
                {
                    UpdateItem u = batch.CreateNewItem();

                    switch (row.RowState)
                    {
                        case DataRowState.Added:
                            u.Command = UpdateCommands.Insert;
                            break;
                        case DataRowState.Deleted:
                            u.Command = UpdateCommands.Delete;
                            break;
                        case DataRowState.Modified:
                            u.Command = UpdateCommands.Update;
                            break;
                        case DataRowState.Unchanged:
                            continue;
                    }

                    if (u.Command == UpdateCommands.Delete)
                        row.RejectChanges();

                    if (u.Command != UpdateCommands.Insert)
                    {
                        if (!(row[clientIdColumn] is DBNull))
                        {
                            u.ListItemID = (int)row[clientIdColumn];
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (u.Command != UpdateCommands.Delete)
                    {
                        ListItem item = new ListItem();
                        Exception e;

                        MapDataRowToListItem(row, item, out e);
                        u.ChangedItemData = item;
                        if (e != null && SyncTracer.IsErrorEnabled())
                            SyncTracer.Error(e.ToString());
                    }

                    batch.Add(u);
                    IdMapping[u.ID] = row;

                    if (u.Command == UpdateCommands.Delete)
                        row.Delete();
                }

                if (batch.Count != 0)
                {
                    //try
                    //{
                        UpdateResults results = connection.UpdateListItems(this.ListName, batch);
                        // FIX: errors must be handled appropriately
                        foreach (UpdateResult r in results)
                        {
                            if (!r.IsSuccess())
                            {
                                if (!IdMapping.ContainsKey(r.UpdateItemID))
                                    throw new InvalidOperationException(
                                        String.Format(CultureInfo.CurrentCulture, Messages.NoIDMapping, r.UpdateItemID));

                                DataRow clientRow = IdMapping[r.UpdateItemID];
                                errors.Add(CreateSyncError(r, clientRow));
                            }
                        }
                    //}
                    //catch (Exception ex)
                    //{
                    ////usually connection error
                    //    foreach (UpdateItem item in batch)
                    //    {
                    //        if (!IdMapping.ContainsKey(item.ID))
                    //            throw new InvalidOperationException(
                    //                String.Format(CultureInfo.CurrentCulture, Messages.NoIDMapping, r.UpdateItemID));

                    //        DataRow clientRow = IdMapping[item.ID];
                    //        errors.Add(CreateSyncError(new UpdateResult(, clientRow));
                    //    }
                    //}
                }
                //END SEND SEGMENT
            }

            if (errors.Count == 0)
                errors = null;
        }