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

标签 c# mysql methods datareader

在我的整个程序中,我将重复使用(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 */ }

但是,我收到一条消息说“阅读器关闭时读取尝试无效!” 我怎样才能纠正这个问题并让它发挥作用?或者更确切地说,是否有更合适的方法来做到这一点?我如何确保我的连接/阅读器在使用后关闭?

最佳答案

您可以使您的方法通用并注入(inject)一个函数以在读取器上工作,然后返回函数的输出而不是读取器:

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,所以我为reader添加了using语句
  • 我使用 ADO.NET 接口(interface)方法而不是构造函数来创建命令
  • 我删除了 catch block ,因为当您离开 using block 时连接会自动关闭,并且 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 在连接字符串中设置数据库,这比在 select 语句前面加上 USE 更可取数据库子句。

关于C# 和 MySQL - 返回 DataReader(或其内容)的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25671725/

相关文章:

mysql - 通过主键和2个索引对mysql表进行分区和子分区以提高性能

c# - MVC项目中包之间的歧义

c# - 将控件作为参数传递是否会导致足够的性能损失?

mysql - 一个表可以有同一个表的两个外键吗?

class - 如何在 MATLAB 中定义一个类,该类使用在单独的文件(@ 文件夹中)中定义的方法?

java - 方法引用 Static - 小程序示例给建议

vba - 如何在不主动选择每个工作表的情况下在多个工作表中运行一个方法

c# - 在 C# 中更改网格的颜色 (Windows Phone 8)

c# - 我应该在哪个页面上为具有布局和部分 View 的 ASP.NET Web 应用程序添加 ajax 查询?

c# - MySqlException : Field 'id' doesn't have a default value - Entity Framework Core 2. 1