Hi guys, I am switching from Java to C #, now that I realized that I prefer the features of C # over Java, but I have this little problem. In MySQL Connector / J and JDBC, I believe that one of my applications allowed several PreparedStatement to be executed, and the other is open, for example, I could execute a query that returns a ResultSet , and while the ResultSet is still open, I could open another PreparedStatement and get another ResultSet , or I could just perform an update based on the data received from my first ResultSet (i.e., Insert the salt value and update the password column using the SHA512 hash when I understand that the line has a plaintext password in the password column )
However, with Connector / NET, I realized when I try to do this, I get this error: MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first.
Is there an easy way to fix this error, perhaps any other implementations of the MySQL .NET bridge? I really do not want to create many database connections in one application, although I may need to create it for each thread in my application (as in ThreadLocal). A ThreadLocal DB connection will help when I execute two queries simultaneously in two different methods, but obviously I cannot separate these two commands from different threads, and I don't want to create extra threads.
By the way, here is the code itself. Yes, I can move the update code before closing my reader, but I have many other similar methods, and some of them are more difficult to fix than this:
MySqlConnection con = DatabaseConnection.GetConnection(); MySqlCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT `id`,`password`,`salt`,`pin`,`gender`,`birthday` FROM `accounts` WHERE `name` = '" + AccountName + "'"; MySqlDataReader reader = cmd.ExecuteReader(); if (reader.Read()) { AccountId = reader.GetInt32(0); string passhash = !reader.IsDBNull(1) ? reader.GetString(1) : null; string salt = !reader.IsDBNull(2) ? reader.GetString(2) : null; m_pin = !reader.IsDBNull(3) ? reader.GetString(3) : null; Gender = !reader.IsDBNull(4) ? reader.GetByte(4) : WvsCommon.Gender.UNDEFINED; m_birthday = !reader.IsDBNull(5) ? reader.GetInt32(5) : 0; if (!HashFunctions.HashEquals(pwd, HashAlgorithms.SHA512, passhash + salt)) { if (passhash == pwd || salt == null && HashFunctions.HashEquals(pwd, HashAlgorithms.SHA1, passhash)) { salt = HashFunctions.GenerateSalt(); passhash = HashFunctions.GenerateSaltedSha512Hash(pwd, salt); MySqlCommand update = con.CreateCommand(); update.CommandText = "UPDATE `accounts` SET `password` = '" + passhash + "', `salt` = '" + salt + "' WHERE `id` = " + AccountId; update.ExecuteNonQuery(); update.Dispose(); } } } reader.Close(); cmd.Dispose();
If moving the update code is the only option, or if this is the best option, I suppose I will have to work with it, but first I want to get more ideas on the other options, and then choose the option.