C#和MySQL-返回DataReader(或其内容)的方法

本文关键字:方法 MySQL- 返回 DataReader | 更新日期: 2023-09-27 18:20:50

在整个程序中,我将重复使用(MySQL的)SELECT命令。每一次,我都必须建立联系和东西。我正在考虑制作一个方法,接收SELECT命令字符串并返回参数的等效DataReader。我想这将帮助我减少每次必须生成的大量代码。

我想以这样的方式使用它:

MySqlDataReader myReader = myObj.loadDataToReader("SELECT * FROM tblSample");

然后,我可以像普通的MySqlDataReader一样操作myReader。然而,我担心的是,在使用数据读取器时,连接必须是打开的,当然,它的相关内容(读取器和连接)需要关闭等等(我认为这是一种传统的安全措施)。我一直在看互联网上的东西,似乎找不到如何做到这一点的提示。

我正在尝试,我有以下代码行:

public MySqlDataReader loadDataToReader(string selectCommand)
{
    MySqlDataReader myReader = null;
    string myConnectionString = "Data Source = " + server + "; User = " + user + "; Port = 3306; Password = " + password + ";";
    string useDataBaseCommand = "USE " + dbName + ";";
    using (MySqlConnection myConnection = new MySqlConnection(myConnectionString))
    {
        using (MySqlCommand myCommand = new MySqlCommand(useDataBaseCommand + selectCommand, myConnection))
        {
            try
            {
                myConnection.Open();
                myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
            }
            catch (Exception ex)
            {
                myConnection.Close();
                MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return myReader;
        }
    }
}

在另一个类的方法中,我创建了一个对象,以便能够使用上面定义的方法,其方式如下:

string selectTableCommand = "SELECT * FROM tblusers WHERE Username = ''" + txtID.Text + "'' AND Password = ''" + txtPassword.Text + "'';";
MySQLOperations objSQLOperations = new MySQLOperations("localhost", "root", "mypass", "mydatabase");
MySqlDataReader myDataReader = objSQLOperations.loadDataToReader(selectTableCommand);
if (myDataReader.Read() && txtPassword.Text.Equals(myDataReader["Password"].ToString()))
     { /* do something */ }
else
     { /* do something */ }

然而,我收到一条消息说:"当阅读器关闭时,尝试阅读无效!"我该如何纠正并使其发挥作用?或者更确切地说,有没有更合适的方法来做到这一点?我该如何确保我的连接/阅读器在使用后关闭?

C#和MySQL-返回DataReader(或其内容)的方法

您可以使方法通用,并注入一个函数来处理读取器,然后返回函数的输出,而不是读取器:

public T LoadDataToReader<T>(string selectCommand, Func<IDataReader,T> ProcessResults)
{
    string myConnectionString = "Data Source = " + server + "; User = " + user + "; Port = 3306; Password = " + password + ";";
    string useDataBaseCommand = "USE " + dbName + ";";
    using (var myConnection = new MySqlConnection(myConnectionString))
    {
        myConnection.Open();
        using (var myCommand = myConnection.CreateCommand())
        {
            myCommand.CommandText = useDataBaseCommand + selectCommand;
            using(var myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection))
            {
               return ProcessResults(myReader);
            }
        }
    }
}

我还做了一些其他更改:

  • IDataReader实现了IDisposable,所以我为阅读器添加了using语句
  • 我使用ADO.NET接口方法来创建命令,而不是构造函数
  • 我删除了catch块,因为当您离开using块时,连接会自动关闭,并且UI代码(例如MessageBox)不属于DAL代码。相反,这应该作为对该方法的调用的try/catch来完成
  • 我将函数的第一个字母大写,以使其符合.NET编码标准

然后,您只需按如下方式使用它:

public static string GetStringData(IDataReader reader)
{
  var ord_name = reader.GetOrdinal("Name");
   if(reader.Read())
     return reader.GetString(ord_name);
   return null;
}
public static IEnumerable<Foo> GetFoos(IDataReader reader)
{
   var ord_name = reader.GetOrdinal("Name");
   var foos = new List<Foo>();
   while(reader.Read())
     foos.Add(new Foo {Name = reader.GetString(ord_name)});
   return foos;
}
static void Main(string[] args)
{
   var program = new Program();
   try
   {
      var name = program.LoadDataToReader("SELECT name FROM thename", GetStringData);
   }
   catch(Exception ex)
   {
      MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
   }
   try
   {
      var foos = program.LoadDataToReader("SELECT foos FROM footable", GetFoos);
   }
   catch(Exception ex)
   {
      MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
   }
}

此外,您可能应该传入连接字符串,而不是从字段构建它。或者,您可以为整个连接字符串设置一个字段(只构建一次,而不是每次执行)并使用它。

此外,数据库可以用Initial CatalogDatabase设置在连接字符串中,这比用USE database子句作为select语句的前缀更可取。