public async Task <ActionResult <int> > AddAsync([FromForm] UploadRequest uploadRequest)
        {
            // Only associate it with the user if they requested that it be added to their progress.
            string userId = uploadRequest.AddToProgress && User.Identity.IsAuthenticated
                ? _userManager.GetUserId(User)
                : null;

            SavedGame savedGame = SavedGame.Parse(uploadRequest.EncodedSaveData);

            if (savedGame == null)
            {
                // Not a valid save
                return(BadRequest());
            }

            // Kick off a clan update in parallel
            string gameUserId     = savedGame.Object.Value <string>("uniqueId");
            string passwordHash   = savedGame.Object.Value <string>("passwordHash");
            Task   updateClanTask = _clanManager.UpdateClanAsync(userId, gameUserId, passwordHash);

            PlayStyle playStyle;

            if (uploadRequest.PlayStyle.HasValue)
            {
                playStyle = uploadRequest.PlayStyle.Value;
            }
            else
            {
                Website.Models.Api.Users.UserSettings userSettings = await _userSettingsProvider.GetAsync(userId);

                playStyle = userSettings.PlayStyle.GetValueOrDefault(PlayStyle.Hybrid);
            }

            // unixTimestamp is in milliseconds instead of seconds
            DateTime saveTime = (savedGame.Object.Value <double>("unixTimestamp") / 1000).UnixTimeStampToDateTime();

            AncientLevelsModel ancientLevels = new(
                _gameData,
                savedGame);
            OutsiderLevelsModel outsiderLevels = new(
                _gameData,
                savedGame);
            ComputedStats computedStats = new(savedGame);

            int uploadId;

            using (IDatabaseCommand command = _databaseCommandFactory.Create())
            {
                await command.BeginTransactionAsync();

                // Insert Upload
                command.CommandText = @"
	                INSERT INTO Uploads(UserId, UploadContent, PlayStyle, SaveTime)
                    VALUES(@UserId, @UploadContent, @PlayStyle, @SaveTime);
                    SELECT SCOPE_IDENTITY();";
                command.Parameters  = new Dictionary <string, object>
                {
                    { "@UserId", userId },
                    { "@UploadContent", uploadRequest.EncodedSaveData },
                    { "@PlayStyle", playStyle.ToString() },
                    { "@SaveTime", saveTime },
                };
                uploadId = Convert.ToInt32(await command.ExecuteScalarAsync());

                // Insert computed stats
                command.CommandText = @"
                    INSERT INTO ComputedStats(
                        UploadId,
                        TitanDamage,
                        SoulsSpent,
                        HeroSoulsSacrificed,
                        TotalAncientSouls,
                        TranscendentPower,
                        Rubies,
                        HighestZoneThisTranscension,
                        HighestZoneLifetime,
                        AscensionsThisTranscension,
                        AscensionsLifetime)
                    VALUES(
                        @UploadId,
                        @TitanDamage,
                        @SoulsSpent,
                        @HeroSoulsSacrificed,
                        @TotalAncientSouls,
                        @TranscendentPower,
                        @Rubies,
                        @HighestZoneThisTranscension,
                        @HighestZoneLifetime,
                        @AscensionsThisTranscension,
                        @AscensionsLifetime);";
                command.Parameters  = new Dictionary <string, object>
                {
                    { "@UploadId", uploadId },
                    { "@TitanDamage", computedStats.TitanDamage },
                    { "@SoulsSpent", computedStats.HeroSoulsSpent },
                    { "@HeroSoulsSacrificed", computedStats.HeroSoulsSacrificed },
                    { "@TotalAncientSouls", computedStats.TotalAncientSouls },
                    { "@TranscendentPower", computedStats.TranscendentPower },
                    { "@Rubies", computedStats.Rubies },
                    { "@HighestZoneThisTranscension", computedStats.HighestZoneThisTranscension },
                    { "@HighestZoneLifetime", computedStats.HighestZoneLifetime },
                    { "@AscensionsThisTranscension", computedStats.AscensionsThisTranscension },
                    { "@AscensionsLifetime", computedStats.AscensionsLifetime },
                };
                await command.ExecuteNonQueryAsync();

                // Insert ancient levels
                StringBuilder ancientLevelsCommandText = new("INSERT INTO AncientLevels(UploadId, AncientId, Level) VALUES");
                Dictionary <string, object> ancientLevelsParameters = new()
                {
                    { "@UploadId", uploadId },
                };
                bool isFirstAncient = true;
                foreach (KeyValuePair <int, BigInteger> pair in ancientLevels.AncientLevels)
                {
                    if (!isFirstAncient)
                    {
                        ancientLevelsCommandText.Append(',');
                    }

                    // Looks like: (@UploadId, @AncientId{AncientId}, @AncientLevel{AncientId})
                    string idParamName    = "@AncientId" + pair.Key;
                    string levelParamName = "@AncientLevel" + pair.Key;
                    ancientLevelsCommandText.Append("(@UploadId,");
                    ancientLevelsCommandText.Append(idParamName);
                    ancientLevelsCommandText.Append(',');
                    ancientLevelsCommandText.Append(levelParamName);
                    ancientLevelsCommandText.Append(')');

                    ancientLevelsParameters.Add(idParamName, pair.Key);
                    ancientLevelsParameters.Add(levelParamName, pair.Value.ToTransportableString());

                    isFirstAncient = false;
                }

                command.CommandText = ancientLevelsCommandText.ToString();
                command.Parameters  = ancientLevelsParameters;
                await command.ExecuteNonQueryAsync();

                // Insert outsider levels
                StringBuilder outsiderLevelsCommandText = new("INSERT INTO OutsiderLevels(UploadId, OutsiderId, Level) VALUES");
                Dictionary <string, object> outsiderLevelsParameters = new()
                {
                    { "@UploadId", uploadId },
                };
                bool isFirstOutsider = true;
                foreach (KeyValuePair <int, long> pair in outsiderLevels.OutsiderLevels)
                {
                    if (!isFirstOutsider)
                    {
                        outsiderLevelsCommandText.Append(',');
                    }

                    // Looks like: (@UploadId, @OutsiderId{OutsiderId}, @Level{OutsiderId})
                    string idParamName    = "@OutsiderId" + pair.Key;
                    string levelParamName = "@OutsiderLevel" + pair.Key;
                    outsiderLevelsCommandText.Append("(@UploadId,");
                    outsiderLevelsCommandText.Append(idParamName);
                    outsiderLevelsCommandText.Append(',');
                    outsiderLevelsCommandText.Append(levelParamName);
                    outsiderLevelsCommandText.Append(')');

                    outsiderLevelsParameters.Add(idParamName, pair.Key);
                    outsiderLevelsParameters.Add(levelParamName, pair.Value);

                    isFirstOutsider = false;
                }

                command.CommandText = outsiderLevelsCommandText.ToString();
                command.Parameters  = outsiderLevelsParameters;
                await command.ExecuteNonQueryAsync();

                command.CommitTransaction();
            }

            // Wait for the task to finish, but don't fail the request if it fails
            try
            {
                await updateClanTask;
            }
            catch (Exception e)
            {
                Dictionary <string, string> properties = new()
                {
                    { "UploadId", uploadId.ToString() },
                };
                _telemetryClient.TrackException(e, properties);
            }

            return(uploadId);
        }