抛出异常:' System.Collections.Generic.KeyNotFoundException'在使用SELECT查询时在mscorlib.dll中

时间:2018-05-14 12:28:22

标签: c# mysql sql winforms xamarin.forms

try
{
    string connString = "server=db4free.net;port=3306;database=secretdb;user id=secret;password=secret;charset=utf8";
    MySqlConnection conn = new MySqlConnection(connString);
    conn.Open();
    MySqlCommand cmd = new MySqlCommand("SELECT School_Name FROM schools WHERE School_ID=@id", conn);
    cmd.Parameters.AddWithValue("@id", "1");
    var schoolName = cmd.ExecuteScalar();
    label1.Text = schoolName.ToString();
    conn.close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

上面的代码返回异常抛出异常:' System.Collections.Generic.KeyNotFoundException'在mscorlib.dll中

但是每当我使用诸如 INSERT,UPDATE和DELETE之类的查询时,它都能正常工作。就像下面的代码一样:

try
{
    string connString = "server=db4free.net;port=3306;database=secretdb;user id=secret;password=secret;charset=utf8";
    MySqlConnection conn = new MySqlConnection(connString);
    conn.Open();
    MySqlCommand cmd = new MySqlCommand("INSERT INTO schools(School_Name,School_Address) VALUES(@name,@address)", conn);
    cmd.Parameters.AddWithValue("@name", "Sample Name");
    cmd.Parameters.AddWithValue("@address", "Sample Address");
    cmd.ExecuteNonQuery();
    label1.Text = "Success";
    conn.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

基本上我的问题如下:

  1. 如果在 Xamarin.Forms (在Android中测试)中使用,第一个代码块就可以正常工作。我可以从数据库中选择。
  2. 如果在 Windows Forms App 中使用,则第一个代码块不起作用,并返回所述异常。 Xamarin.Forms和Windows Forms App都在C#上运行,所以我不知道为什么会发生这种情况。
  3. 第二段代码在 Xamarin.Forms Windows Forms App 中运行良好。
  4. 基本上,我可以运行任何SQL查询但不能运行SELECT。

1 个答案:

答案 0 :(得分:1)

首先,您的代码可以在发生异常时保持连接打开。 conn.Close()应移至finally块。 其次,要查询​​值,您应该使用cmd.ExecuteReader()方法,该方法将返回MySqlDataReader个对象;要处理它,您可以使用using()构造。 ExecuteScalar()方法用于插入/更新/删除语句,并返回受影响的行数。

第三,但同样重要:考虑将与数据库相关的代码移动到Repository类,然后从Form逻辑中调用存储库类代码。这样您就可以获得可重复使用的代码。 存储库类的起点的简单示例:

public class Repository
{
    public string ConnectionString { get; private set; }

    public Repository(string connectionString)
    {
        this.ConnectionString = connectionString;
    }

    public string GetSchoolNameById(int id)
    {
        string schoolName = null;
        MySqlConnection conn = null;
        try
        {
            conn = new MySqlConnection(this.ConnectionString);
            conn.Open();
            using (MySqlCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = "SELECT School_Name FROM schools WHERE School_ID=@id";
                cmd.Parameters.AddWithValue("@id", id);
                using (var rdr = cmd.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        if (!rdr.IsDBNull(rdr.GetOrdinal("School_Name")))
                        {
                            schoolName = rdr.GetString(rdr.GetOrdinal("School_Name"));
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // maybe log exception here, or rethrow it if you want
            // the consumer to manage it. This depends on how you plan to build your software architecture.
        }
        finally
        {
            // this code will run always, either if everything ran correctly or if some exception occurred in the try block.
            if (conn != null)
            {
                conn.Close();
                conn.Dispose();
            }
        }
        return schoolName;
    }

}

然后,您的表单代码可以简单如下:

    Repository rep = new Repository("server=db4free.net;port=3306;database=secretdb;user id=secret;password=secret;charset=utf8");
    try
    {
        // the try/catch is necessary if you have decided to re-throw the exception in the Repository.GetSchoolNameById method
        label1.Text = rep.GetSchoolNameById(1);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }