一个通用函数,它将 return 来自本地 MySQL 数据库的 SELECT 查询的结果 - C# .Net 4.6.1

A generic function that will return the results of a SELECT query from a local MySQL database - C# .Net 4.6.1

我正在使用 MySQL 本地数据库,连接到数据库不是问题(不再)。我有一个小型数据库,大约有 6 个不同的 table,每个大约有 4-6 列,行 <100(不处理大数据)。

我正在创建一个 WPF 应用程序,它只需要 SELECT 来自这些数据库的数据,它永远不需要添加到它们。数据库中充满了静态数据,我需要对其进行 运行 SELECT 语句,然后使用结果显示在我的 WPF 应用程序中。

我需要在我的 DBHandler class 中创建一个函数,然后可以从我系统中的任何其他 class 调用该函数,以使用指定的 SELECT 语句查询数据库,然后使用结果。问题是我的查询会有所不同 - 有时我可能会要求一列,例如;

(SELECT id FROM students WHERE name = 'Conor')

有时我可能会在更复杂的语句中调用多行..比如这个(伪):

(SELECT name, address FROM destinations WHERE long, lat intersects_with (SELECT long, lat FROM trains))

每当我用查询调用这个函数时,我总是期待数据响应的格式,所以如果我只是 return 一个 List<> 或数组,访问数据应该没有问题即使该函数是通用的而不是特定于一个查询或 table.

到目前为止我试过这个:

    public static MySqlDataReader Query(string SQLQuery)
    {
        using (MySqlConnection con = new MySqlConnection(connectionString))
        {
            con.Open();

            MySqlCommand command = new MySqlCommand(SQLQuery, con);

            MySqlDataReader reader = command.ExecuteReader();

            return reader;
        }
    }

    // Some other class
    MySqlDataReader reader = DBHandler.Query("SELECT * FROM destinations");

    while (reader.Read())
    {
        MessageBox.Show(reader[0].ToString());
    }

这不起作用,因为它抱怨 reader 已关闭。我想我不能简单地 return 一个 MySqlDataReader 对象。

我的下一个想法是进行实际查询,return 查询函数中的所有数据,然后存储所有结果,然后可以 returned。但是 how I return 数据是我的主要问题,因为它需要对于变量 SELECT 查询是通用的,所以它不能有固定的大小行数或列数 returned。我想也许我可以将它存储在 List<> 中,或者 List<> 中的 List<>,但我真的不确定如何布局它。

我知道这要求很多,但它让我感到困惑 - 我不知道如何制作这个通用 SELECT 函数,但我知道它会非常有用,因为我只需要每当我需要在系统的另一部分获取数据时调用它。

谢谢!

a reader在线,需要在里面循环(using connection),因为如果离开using,connction会被释放关闭

您不能在连接已关闭时尝试使用 DataReader。因此,当您的代码退出 using 块时,连接也会关闭 reader。但是,您可以将接收 MySqlDataReader 的 Action delegate 传递给您的查询方法。此函数将由 Query 的调用者定义,因此您可以为不同的表自定义它,同时保持用于打开、查询和读取数据库的样板代码的通用方法。

public static MySqlDataReader Query(string SQLQuery, Action<MySqlDataReader> loader)
{
    using (MySqlConnection con = new MySqlConnection(connectionString))
    {
        con.Open();

        using(MySqlCommand command = new MySqlCommand(SQLQuery, con))
        using(MySqlDataReader reader = command.ExecuteReader())
        {
           // here you can pass the reader, you are still inside the using block
           while(reader.Read())
              loader.Invoke(reader)
        }
    }
}

您可以在调用方代码中编写

List<Destination> destinations = new List<Destination>();
MySqlDataReader reader = DBHandler.Query("SELECT * FROM destinations", dataLoaderForDestination);
Console.WriteLine("Loaded " + destinations.Count + " destinations");

private void dataLoaderForDestination(MySqlDataReader reader)
{
    Destination dest = new Destination();
    dest.Address = reader.GetString(0);
    dest.Nation = reader.GetInt32(1);
    ...
    destinations.Add(dest);
}

当然,在代码的不同位置,您可以将引用传递给为查询返回的不同数据集量身定制的不同 Action 委托

List<Student> students = new List<Student>();
private void dataLoaderForStudents(MySqlDataReader reader)
{
    Student st = new Student();
    st.Name = reader.GetString(0);
    st.Class = reader.GetInt32(1);
    students.Add(st);
}