【问题标题】:MySQL Parameters.AddWithValue not working C#MySQL Parameters.AddWithValue 不工作 C#
【发布时间】:2021-02-13 18:30:19
【问题描述】:

我一直在尝试编写连接代码来连接数据库。进展顺利,但我遇到了一个我似乎无法解决的奇怪问题。

当我尝试向查询中添加参数时,它不会检索数据。但是当我切换出参数时,它确实会检索到正确的数据。

数据访问层如下所示。 (我知道这很不安全,但我才刚刚开始):

public static class UserDA
{
    private static MySqlCommand cmd = null;
    private static DataTable dt;
    private static MySqlDataAdapter da;

    public static User RetrieveUser(String username)
    {
        // Create the query
        const String query = "SELECT `Username`, `Password` FROM login WHERE `Username` = '@Username';";
        cmd = DbHelper.Select(
            query, 
            new Dictionary<String, String> 
            {
                {"@Username", username}
            });

        //Setup model
        User user = null;
        if (cmd == null) return null;

        // Get the data and add it to the user model
        dt = new DataTable();
        da = new MySqlDataAdapter(cmd);
        da.Fill(dt);
        foreach (DataRow dataRow in dt.Rows)
        {
            user = new Models.User(
                dataRow["Username"].ToString(),
                dataRow["Password"].ToString());
        }

        return user;
    }
}

Select 方法如下所示:

public static class DbHelper
{
    private static MySqlConnection _connection;
    private static MySqlCommand _cmd;
    private static DataTable _dataTable;
    private static MySqlDataAdapter _adapter;

    public static void EstablishConnection()
    {
        // Gets a connection to the database. Code works.
    }

    /// <summary>
    /// Give the query and a dict with the param name and value
    /// </summary>
    public static MySqlCommand Select(String query, Dictionary<String , String> param)
    {
        try
        {
            if (_connection != null)
            {
                _connection.Open();
                _cmd = _connection.CreateCommand();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = query;
                foreach (KeyValuePair<String, String> keyValuePair in param)
                {
                    _cmd.Parameters.AddWithValue(keyValuePair.Key, keyValuePair.Value);
                }

                _cmd.ExecuteScalar();
                _connection.Close();
            }
        }
        catch (Exception e)
        {
            _connection?.Close();
        }
        return _cmd;
    }
}

最后是用户模型:

public class User
{
    public String Username;
    public String Password;

    public User(String username = "", String password = "")
    {
        Username = username;
        Password = password;
    }
}

当我尝试从中获取数据时会出现问题。如果我使用带有参数的选择查询,它不起作用,但只要我将参数更改为实际值,它就会很好地检索它。在这一点上,我真的很挠头。我是不是在某个地方忘记了一步?

谢谢!

【问题讨论】:

  • private static MySqlConnection _connection; 是一个等待发生的错误。您可能不会跨线程共享 MySqlConnection 对象:mysqlconnector.net/troubleshooting/connection-reuse 相反,它们的创建成本非常低(由于连接池),因此只需在需要时创建一个新对象。还可以使用using 语句(using (var connection = new MySqlConnection(connectionString)) { ... },您可以删除对Close(和异常处理程序)的显式调用;它将自动关闭。
  • 最后,像stackexchange.github.io/Dapper 这样的库已经为您编写了所有这些代码;我强烈建议使用现成的解决方案,而不是尝试自己编写。
  • 我一定要看看图书馆。不过我还是想先自己做一个,因为它是我 atm 的学习工具。我第一次真正用 C# 编写连接器。之前只在php中做过。
  • 是的,自己编写代码是了解 ADO.NET 工作原理以及了解 Dapper 在后台做什么的绝佳方式。

标签: c# mysql mysql.data


【解决方案1】:

尝试删除 SQL 代码中 @Username 周围的引号。

之前

SELECT `Username`, `Password` FROM login WHERE `Username` = '@Username';

之后

SELECT `Username`, `Password` FROM login WHERE `Username` = @Username;

如果这不起作用,请尝试将您的字典从 更改为

【讨论】:

    【解决方案2】:

    从您的代码中删除它

      _cmd.ExecuteScalar();
                    _connection.Close();
    

    为了更好的编码风格,我强烈建议将用户类更改为

    public class User
    {
        public string Username {get; set;}
        public string Password {get; set;}
    
     public User()
    {
    }
        public User(string username, string password)
        {
            Username = username;
            Password = password;
        }
    }
    ```
    

    【讨论】:

    • 我同意用户的编码风格,但我为什么要删除 _cmd.ExecuteScalar();和 _connection.Close();。这就是获取数据的全部内容。或者你的意思是我应该把它移到我实际运行代码的地方?
    • 我的意思是我不明白如果你没有得到任何数据,为什么要运行 cmd?当连接关闭时,您不能使用 cmd 对象。使用适配器读取一些数据是一种不好的做法。使用 datareader 效率更高。
    • 所以我应该使用 _cmd.ExecuteReader();并返回 dataReader 并使用它。
    • 当您将适配器保存在计算机内存中时,它仅适用于桌面应用程序。没有人将适配器用于 Web 应用程序。服务器发送响应后处理所有数据。
    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 2012-03-20
    • 2012-06-10
    • 2014-10-23
    相关资源
    最近更新 更多