数据库
首页 > 数据库> > .net – MySQL Connector / NET连接每个连接多个DataReader?

.net – MySQL Connector / NET连接每个连接多个DataReader?

作者:互联网

嘿伙计们,我正在从Java迁移到C#现在我已经意识到我更喜欢C#语言功能而不是Java语言,但我有这个小问题.在MySQL Connector / J和JDBC中,我相信我的一个应用程序允许执行多个PreparedStatements而另一个是打开的,就像我可以执行返回ResultSet的查询一样,当ResultSet仍然打开时,我可以打开另一个PreparedStatement并获取另一个ResultSet,或者我可以根据我从第一个ResultSet获得的数据执行更新(即,当我意识到该行有明文密码时,插入一个salt值并使用SHA512哈希更新密码列密码栏).

但是,使用Connector / NET,我已经意识到每当我尝试这样做时,我都会收到此错误:
MySql.Data.MySqlClient.MySqlException:已经有一个与此Connection关联的打开DataReader,必须先关闭它.

有没有一种简单的方法来修复此错误,可能是MySQL到.NET桥的任何其他实现?我真的不想在一个应用程序中创建大量的数据库连接,尽管我可能想为我的应用程序中的每个线程创建一个(如在ThreadLocal中).当我在两种不同的方法中同时执行两个查询时,ThreadLocal数据库连接将有所帮助,但显然我不能将这两个命令分成不同的线程,我不想创建多余的线程.

顺便说一句,这是代码本身.是的,我可以将更新代码移到我关闭阅读器后,但我有更多类似的方法,其中一些比这个更难修复:

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();

如果移动更新代码是唯一的可能性,或者如果它是最好的,我想我将不得不做它,但我想先了解其他可能性,然后选择一个选项.

解决方法:

不,我打赌在java世界中也是如此.

正在积极使用/保持连接以检索该数据,如果在java世界中有效,那是因为它执行以下操作之一:

>读取/缓存整个结果集
>在幕后单独进行连接

我在一个问题上看不多,你只需要移动阅读器.关闭代码中的适当位置.也就是说,无论如何都应该检查代码,因为如果发生异常,将无法正确调用dispose / close调用.使用using语句可以确保所有内容都被正确释放,在代码的修改版本下面进行这些更改(以及其他一些使其不太深入的更改):

using(MySqlConnection con = DatabaseConnection.GetConnection())
using(MySqlCommand cmd = con.CreateCommand())
{
    cmd.CommandText = "SELECT `id`,`password`,`salt`,`pin`,`gender`,`birthday` FROM `accounts` WHERE `name` = '" + AccountName + "'";
    using(MySqlDataReader reader = cmd.ExecuteReader())
    {
        if(!reader.Read()) return;
        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;
        reader.Close();
        if (HashFunctions.HashEquals(pwd, HashAlgorithms.SHA512, passhash + salt))
            return;
        if(passhash != pwd && !(salt == null && HashFunctions.HashEquals(pwd, HashAlgorithms.SHA1, passhash)))
            return;
        salt = HashFunctions.GenerateSalt();
        passhash = HashFunctions.GenerateSaltedSha512Hash(pwd, salt);
        using(MySqlCommand update = con.CreateCommand())
        {
           update.CommandText = "UPDATE `accounts` SET `password` = '" + passhash + "', `salt` = '" + salt + "' WHERE `id` = " + AccountId;
           update.ExecuteNonQuery();
        }
    }
}

标签:mysql,net,database-connection,sqldatareader,mysql-connector
来源: https://codeday.me/bug/20190626/1298859.html