Unity+C#操作SQL Server查询最高分触发IndexOutOfRangeException
Hey there! Let's break down why you're hitting that IndexOutOfRangeException and fix it up.
Your SQL query and your data reading logic are out of sync. Let's look at your query first:
SELECT MAX (PlayerScore1) FROM ScoreQuiz1
This query only returns one single value — the highest score. But your code tries to read three fields: ID, PlayerName1, and PlayerScore1. Since the first two fields don't exist in the query result, the data reader throws that index out of range error.
Worse, even if you got the max score, this query doesn't tell you which player has that score. You need a query that fetches the full record for the highest-scoring player.
1. Fix the SQL Query
Instead of just getting the max score value, fetch the full top record by sorting your table and grabbing the first entry. This will give you the ID, player name, and their highest score:
SELECT TOP 1 ID, PlayerName1, PlayerScore1 FROM ScoreQuiz1 ORDER BY PlayerScore1 DESC
(If multiple players have the same highest score, this will pick the first one in the table. If you want the most recent one, add , ID DESC to the ORDER BY clause.)
2. Update Your BuscarScoreFinal1 Method
Replace your query with the corrected one, and clean up the logic a bit (no need for a while loop since we're only fetching one record):
public bool BuscarScoreFinal1() { SqlDataReader dataReader = null; // Use the corrected query string query = "SELECT TOP 1 ID, PlayerName1, PlayerScore1 FROM ScoreQuiz1 ORDER BY PlayerScore1 DESC"; if (RunQuery(query, ref dataReader)) { // Check if there's a record to read if(dataReader.Read()) { id1 = dataReader.GetInt32(dataReader.GetOrdinal("ID")); PlayerName1 = dataReader.GetString(dataReader.GetOrdinal("PlayerName1")); PlayerScore1 = dataReader.GetInt32(dataReader.GetOrdinal("PlayerScore1")); } } // Always clean up the reader if (dataReader != null) dataReader.Close(); return true; }
3. Tweak Your UI Script Logic
In your UpdateScore script, you're overwriting the Buscardados13 variable twice — the second assignment replaces the first one. Let's fix that to handle connection failures gracefully:
void Start() { var dbInterface = GameObject.Find("DatabaseConnection").GetComponent<DatabaseInterface>(); // First check if connection succeeds bool connected = dbInterface.Connect(); if(connected) { // Only run the query if connected bool querySuccess = dbInterface.BuscarScoreFinal1(); if(querySuccess) { yourText.text = dbInterface.PlayerScore1.ToString(); } else { yourText.text = "Failed to load score"; } } else { yourText.text = "Database connection failed"; } }
Avoid using string.Format for queries unless you're using parameterized values (which you should for user input to prevent SQL injection). In your original code, it was unnecessary since you had no placeholders.
That should resolve the IndexOutOfRangeException and let you correctly display the top player's score!
内容的提问来源于stack exchange,提问作者FRP72

