protected virtual void UpdateLinkDatabase(BulkLoadContext loadContext, BulkLoadSqlContext sqlContext, LinkedList <BulkItemLink> links, ICollection <ItemChange> changes) { // Index all items that were actually changed in db. var touchedItemsMap = changes .GroupBy(x => x.ItemId) .ToDictionary(x => x.First().OriginalItemId, x => x.First().ItemId); // Get links and filter and map them by touched items. if (links.Count == 0) { return; } var linksForTouchedItems = links .Where(x => touchedItemsMap.ContainsKey(x.SourceItemID.Guid)) .Select(x => x.Map(x.SourceItemID.Guid, touchedItemsMap[x.SourceItemID.Guid])); // Create temp table, bulk load temp table, merge records in link database. // The link database is probably not the same physical db as the one were loading data to. var createLinkTempTable = sqlContext.GetEmbeddedSql(loadContext, "Sql.20.CreateLinkTempTable.sql"); var mergeLinkData = sqlContext.GetEmbeddedSql(loadContext, "Sql.21.MergeLinkTempData.sql"); var connectionString = ((SqlServerLinkDatabase)Factory.GetLinkDatabase()).ConnectionString; using (var conn = new SqlConnection(connectionString)) { conn.Open(); var linkSqlContext = new SqlContext(conn); linkSqlContext.ExecuteSql(createLinkTempTable); using (var bulkCopy = new SqlBulkCopy(conn)) { bulkCopy.BulkCopyTimeout = int.MaxValue; bulkCopy.EnableStreaming = true; bulkCopy.DestinationTableName = sqlContext.PostProcessSql(loadContext, "#ItemLinks"); try { bulkCopy.WriteToServer(new ItemLinksReader(() => linksForTouchedItems.GetEnumerator())); } catch (Exception exception) { loadContext.StageFailed(Stage.Load, exception, $"Write to #ItemLinks failed with message: {exception.Message}"); return; } } linkSqlContext.ExecuteSql(mergeLinkData); } }