/// <summary>
        /// Gets or creates a set of <see cref="PlayerSession"/>s from the given list of <see cref="Player"/>s and the current <see cref="Session"/>.
        /// Using caching to reduce MySQL calls and speed up runtime
        /// </summary>
        /// <param name="players">List of <see cref="Player"/>s to get/create</param>
        /// <param name="session">Current <see cref="Session"/></param>
        /// <returns>A set of <see cref="PlayerSession"/> objects, from the database.</returns>
        public ISet<PlayerSession> GetOrCreatePlayerSessions(IList<Player> players, Session session) {
            ISet<PlayerSession> playerSessions = new HashSet<PlayerSession>();

            foreach (Player player in players) {
                PlayerSession playerSession = new PlayerSession();
                playerSession.Player = player;
                playerSession.Session = session;

                if (_cachedPlayerSessions.ContainsKey(player.Name)) {
                    _cachedPlayerSessions.TryGetValue(player.Name, out playerSession);
                    _logger.DebugFormat("Retrieved player session from the cache with ID: {0}", playerSession.Id);
                } else {
                    _getPlayerSession.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name;
                    _getPlayerSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = session.Id;

                    MySqlDataReader getPlayerResult = _getPlayerSession.ExecuteReader();

                    if (getPlayerResult.HasRows) {
                        getPlayerResult.Read();
                        playerSession.Player.Id = getPlayerResult.GetInt32(0);

                        if (getPlayerResult.GetBoolean(1) != playerSession.Player.HasClanTag) {
                            playerSession.Player.Updated = true;
                        }

                        if (getPlayerResult.IsDBNull(2)) {
                            getPlayerResult.Close();
                            CreatePlayerSession(playerSession);
                        } else {
                            playerSession.Id = getPlayerResult.GetInt32(2);
                            playerSession.Length = getPlayerResult.GetInt32(3);
                            playerSession.Played = getPlayerResult.GetBoolean(4);
                            _logger.DebugFormat("Retrieved player session from the database with ID: {0}", playerSession.Id);

                            getPlayerResult.Close();
                        }
                    } else {
                        getPlayerResult.Close();
                        _addPlayer.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name;
                        _addPlayer.Parameters[DatabaseUtil.HAS_CLAN_TAG_KEY].Value = player.HasClanTag;
                        _addPlayer.ExecuteNonQuery();

                        playerSession.Player.Id = GetLastInsertedId();

                        CreatePlayerSession(playerSession);                   
                    }
                    _cachedPlayerSessions.Add(player.Name, playerSession);
                }
                playerSessions.Add(playerSession);
            }

            return playerSessions;
        }
        /// <summary>
        /// Helper method to create a <see cref="PlayerSession"/> in the database
        /// </summary>
        /// <param name="playerSession"><see cref="PlayerSession"/> to create</param>
        /// <returns><see cref="PlayerSession"/> with added database id</returns>
        private PlayerSession CreatePlayerSession(PlayerSession playerSession) {
            _addPlayerSession.Parameters[DatabaseUtil.PLAYER_ID_KEY].Value = playerSession.Player.Id;
            _addPlayerSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = playerSession.Session.Id;
            _addPlayerSession.ExecuteNonQuery();

            playerSession.Id = GetLastInsertedId();
            _logger.DebugFormat("Player session inserted into the database with ID: {0}", playerSession.Id);

            return playerSession;
        }
        /// <summary>
        /// Function to update a <see cref="PlayerSession"/> on the database level
        /// </summary>
        /// <param name="playerSession"><see cref="PlayerSession"/> to update</param>
        public void UpdatePlayerSession(PlayerSession playerSession) {
            if (playerSession.Updated) {
                _updatePlayerSession.Parameters[DatabaseUtil.PLAYED_KEY].Value = playerSession.Played;
                _updatePlayerSession.Parameters[DatabaseUtil.LENGTH_KEY].Value = playerSession.Length;
                _updatePlayerSession.Parameters[DatabaseUtil.PLAYER_TO_SESSION_ID_KEY].Value = playerSession.Id;
                _updatePlayerSession.ExecuteNonQuery();
                _logger.DebugFormat("Player session updated with ID: {0}", playerSession.Id);
            }

            if (playerSession.Player.Updated) {
                _updatePlayer.Parameters[DatabaseUtil.HAS_CLAN_TAG_KEY].Value = playerSession.Player.HasClanTag;
                _updatePlayer.Parameters[DatabaseUtil.PLAYER_ID_KEY].Value = playerSession.Player.Id;
                _updatePlayer.ExecuteNonQuery();
                _logger.DebugFormat("Player updated with ID: {0}", playerSession.Player.Id);
            }
        }