/// <summary>
        /// Gets or creates a set of <see cref="PlayerSessionToMissionSession"/> objects for the given <see cref="MissionSession"/> and set of <see cref="PlayerSession"/> objects
        /// Using caching to reduce MySQL calls and speed up runtime
        /// </summary>
        /// <param name="missionSession"><see cref="MissionSession"/> object used for lookup/creation</param>
        /// <param name="playerSessions">Set of <see cref="PlayerSession"/> objects used for lookup/creation</param>
        /// <returns>Set of <see cref="PlayerSession"/>s from the database</returns>
        public ISet<PlayerSessionToMissionSession> GetOrCreatePSTMS(MissionSession missionSession, ISet<PlayerSession> playerSessions) {
            ISet<PlayerSessionToMissionSession> pstmses = new HashSet<PlayerSessionToMissionSession>();

            // our cached mission session id is invalid, reset the caches
            if (_cachedMissionSessionId != missionSession.Id) {
                _cachedMissionSessionId = missionSession.Id;
                _cachedPlayerSessionsToPSTMS = new Dictionary<int, PlayerSessionToMissionSession>();
            }

            foreach (PlayerSession playerSession in playerSessions) {
                PlayerSessionToMissionSession pstms = new PlayerSessionToMissionSession();
                pstms.PlayerSessionId = playerSession.Id;
                pstms.MissionSessionId = missionSession.Id;

                if (_cachedPlayerSessionsToPSTMS.ContainsKey(playerSession.Id)) {
                    _cachedPlayerSessionsToPSTMS.TryGetValue(playerSession.Id, out pstms);
                    _logger.DebugFormat("PSTMS retrieved from cache with id: {0}", pstms.Id);
                } else {
                    //get
                    _getPSTMS.Parameters[DatabaseUtil.PLAYER_TO_SESSION_ID_KEY].Value = playerSession.Id;
                    _getPSTMS.Parameters[DatabaseUtil.MISSION_TO_SESSION_ID_KEY].Value = missionSession.Id;

                    MySqlDataReader getPTSTMTSResult = _getPSTMS.ExecuteReader();
                    if (getPTSTMTSResult.HasRows) {
                        getPTSTMTSResult.Read();

                        pstms.Id = getPTSTMTSResult.GetInt32(0);
                        pstms.Length = getPTSTMTSResult.GetInt32(1);
                        pstms.Played = getPTSTMTSResult.GetBoolean(2);
                        _logger.DebugFormat("PSTMS retrieved from database with id: {0}", pstms.Id);

                        getPTSTMTSResult.Close();
                    } else {
                        //add
                        getPTSTMTSResult.Close();

                        _addPSTMS.Parameters[DatabaseUtil.PLAYER_TO_SESSION_ID_KEY].Value = playerSession.Id;
                        _addPSTMS.Parameters[DatabaseUtil.MISSION_TO_SESSION_ID_KEY].Value = missionSession.Id;
                        _addPSTMS.ExecuteNonQuery();
                        
                        pstms.Id = GetLastInsertedId();
                        _logger.DebugFormat("PSTMS inserted into the database with id: {0}", pstms.Id);
                    }
                }
                pstmses.Add(pstms);
            }

            return pstmses;
        }
        /// <summary>
        /// Function to update a <see cref="PlayerSessionToMissionSession"/> on the database level
        /// </summary>
        /// <param name="pstms"><see cref="PlayerSessionToMissionSession"/> to update</param>
        public void UpdatePSTMS(PlayerSessionToMissionSession pstms) {
            if (pstms.Updated) {
                _updatePSTMS.Parameters[DatabaseUtil.PLAYED_KEY].Value = pstms.Played;
                _updatePSTMS.Parameters[DatabaseUtil.LENGTH_KEY].Value = pstms.Length;
                _updatePSTMS.Parameters[DatabaseUtil.PLAYER_TO_SESSION_TO_MISSION_TO_SESSION_ID_KEY].Value = pstms.Id;
                _updatePSTMS.ExecuteNonQuery();

                _logger.DebugFormat("PSTMS updated in the database with id: {0}", pstms.Id);
            }
        }