private void AddLink(SqlBatchOperation batch, Item item, ItemLink link)
        {
            var insertCommand = LinkDatabaseCommand.CreateInsertCommand(item.Database.Name, item.ID, link.SourceItemLanguage,
                                                                        link.SourceItemVersion, link.SourceFieldID, link.TargetDatabaseName, link.TargetItemID,
                                                                        link.TargetItemLanguage, link.TargetItemVersion, link.TargetPath, batch);

            batch.AddSqlBatchCommand(insertCommand);
        }
        private ID BatchCompact(Database database, int batchSize, ID lastProcessed)
        {
            Assert.ArgumentNotNull(database, nameof(database));

            var selectSql = $@"
SELECT TOP {batchSize} [ID], [SourceItemID], [SourceLanguage], [SourceVersion] 
FROM [Links] WITH (NOLOCK) 
WHERE [SourceDatabase]=@{LinksTableColumns.Database}";

            if (lastProcessed != ID.Null)
            {
                selectSql += $" AND [ID] > @{nameof(lastProcessed)}";
            }
            selectSql += " ORDER BY [ID]";

            var linkList = new List <Tuple <Guid, ID, Language, Sitecore.Data.Version> >();

            using (var reader = DataApi.CreateReader(selectSql,
                                                     LinksTableColumns.Database, GetString(database.Name, DatabaseNameLength),
                                                     nameof(lastProcessed), lastProcessed))
            {
                DataCount.LinksDataRead.Increment();
                while (reader.Read())
                {
                    var id       = DataApi.GetGuid(0, reader);
                    var itemId   = DataApi.GetId(1, reader);
                    var language = DataApi.GetLanguage(2, reader);
                    var version  = DataApi.GetVersion(3, reader);
                    linkList.Add(new Tuple <Guid, ID, Language, Sitecore.Data.Version>(id, itemId, language, version));
                }
            }

            var  batchOperation = new SqlBatchOperation(DataApi);
            Guid lastId         = Guid.Empty;

            foreach (var row in linkList)
            {
                lastId = row.Item1;
                if (ItemExists(row.Item2, null, row.Item3, row.Item4, database))
                {
                    continue;
                }

                var command = LinkDatabaseCommand.CreateDeleteCommand(row.Item1, batchOperation);
                batchOperation.AddSqlBatchCommand(command);
            }

            batchOperation.FlushBatches();
            return(new ID(lastId));
        }
        private void UpdateLinks(Item item, IEnumerable <ItemLink> newLinks, Func <IEnumerable <Tuple <Guid, ItemLink> > > existingLinks)
        {
            lock (_locks.GetLock(item.ID))
            {
                Factory.GetRetryer().ExecuteNoResult(() =>
                {
                    using (DataProviderTransaction transaction = DataApi.CreateTransaction())
                    {
                        var batch          = new SqlBatchOperation(DataApi);
                        var linksToProcess = existingLinks().ToList();

                        foreach (var link in FilterItemLinks(newLinks))
                        {
                            var existingLink = linksToProcess.FirstOrDefault(l => ItemLinksAreEqual(l.Item2, link));
                            if (existingLink != null)
                            {
                                linksToProcess.Remove(existingLink);
                                continue;
                            }

                            if (link.SourceItemID.IsNull)
                            {
                                continue;
                            }

                            AddLink(batch, item, link);
                        }

                        foreach (var existingLinkId in linksToProcess.Select(l => l.Item1))
                        {
                            RemoveLink(batch, existingLinkId);
                        }

                        batch.FlushBatches();
                        transaction.Complete();
                    }
                });
            }
        }
        private void RemoveLink(SqlBatchOperation batch, Guid itemLinkId)
        {
            var removeCommand = LinkDatabaseCommand.CreateDeleteCommand(itemLinkId, batch);

            batch.AddSqlBatchCommand(removeCommand);
        }