gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 07:06:43 24 4
gpt4 key购买 nike

我正在从 Java 迁移到 C#,现在我意识到我更喜欢 C# 语言的特性而不是 Java 中的特性,但是我有这个小问题。在 MySQL Connector/J 和 JDBC 中,我相信我的一个应用程序允许多个 PreparedStatement s 在另一个打开时执行,就像我可以执行返回 ResultSet 的查询一样而那ResultSet还开着,我可以再开一个PreparedStatement得到另一个 ResultSet或者我可以根据我从第一个 ResultSet 获得的数据执行更新(即,当我意识到该行在密码列中有明文密码时,插入盐值并使用 SHA512 哈希更新密码列)。

但是,使用 Connector/NET 时,我开始意识到每当我尝试这样做时,我都会收到此错误: MySql.Data.MySqlClient.MySqlException: There is already an open DataReader associated with this Connection which must be closed first.

是否有一种简单的方法来修复此错误,也许是 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 世界中有效是因为它执行了以下操作之一:

  • 读取/缓存整个结果集
  • 在幕后的单独连接中完成

我在一个问题上看不多,你只需要移动读者。靠近你代码中的适当位置。也就是说,无论如何您都应该检查该代码,因为如果发生异常,您的处置/关闭调用将不会被正确调用。使用 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();
}
}
}

关于.net - MySQL Connector/NET 连接每个连接多个 DataReader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3685320/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com