使用C#查询MySQL更有效的方法是什么?

使用C#查询MySQL更有效的方法是什么?,c#,mysql,datareader,mysqldatareader,C#,Mysql,Datareader,Mysqldatareader,基于StackOverflow站点的链接(参考资料如下),我提出了这段代码,用于执行从C#应用程序到MySQL数据库的查询 using (var dbConn = new MySqlConnection(config.DatabaseConnection)) { using (var cmd = dbConn.CreateCommand()) { dbConn.Open(); cmd.CommandType = CommandType.Text;

基于StackOverflow站点的链接(参考资料如下),我提出了这段代码,用于执行从C#应用程序到MySQL数据库的查询

using (var dbConn = new MySqlConnection(config.DatabaseConnection))
{
    using (var cmd = dbConn.CreateCommand())
    {
        dbConn.Open();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT version() as Version";

        using (IDataReader reader = cmd.ExecuteReader())
        {
            if (reader.Read())
            {
                Console.WriteLine("Database Version: " + reader.GetString(reader.GetOrdinal("Version")));
            }
        }
    }
}
我遇到的问题是,每次我有一组查询要做时,我都必须构建大量的代码块,因为在应用程序的生命周期中,我不(也不应该)保持连接打开

是否有更有效的方法来构建支持结构(使用s嵌套的
、打开连接等),并传递我的连接字符串和我想要运行的查询并返回结果

参考问题:

  • -特别是答案 特塞尔
这是我看过的三个。还有一些,但我的Google fu现在无法重新查找。所有这些都为如何执行单个查询提供了答案。我希望执行单独的业务逻辑查询(其中一些是重复的),并且不希望重复不需要的代码

我所尝试的: 根据nawfal的评论,我有以下两种方法:

private MySqlDataReader RunSqlQuery(string query)
{
    Dictionary<string, string> queryParms = new Dictionary<string, string>();
    MySqlDataReader QueryResult = RunSqlQuery(query, queryParms);
    return QueryResult;
}

private MySqlDataReader RunSqlQuery(string query, Dictionary<string, string> queryParms)
{
    MySqlDataReader reader = null;
    if (queryParms.Count > 0)
    {
        // Assign parameters
    }

    try
    {
        using (var dbConn = new MySqlConnection(config.DatabaseConnection))
        {
            using (var cmd = dbConn.CreateCommand())
            {
                dbConn.Open();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = query;

                using (reader = cmd.ExecuteReader())
                {
                    return reader;
                }
            }
        }
    }
    catch (MySqlException ex)
    {
        // Oops.
    }

    return reader;
}
private MySqlDataReader RunSqlQuery(字符串查询)
{
Dictionary queryParms=新字典();
MySqlDataReader QueryResult=RunSqlQuery(query,queryParms);
返回查询结果;
}
私有MySqlDataReader RunSqlQuery(字符串查询、字典查询)
{
MySqlDataReader=null;
如果(queryparts.Count>0)
{
//指定参数
}
尝试
{
使用(var dbConn=newmysqlconnection(config.DatabaseConnection))
{
使用(var cmd=dbConn.CreateCommand())
{
dbConn.Open();
cmd.CommandType=CommandType.Text;
cmd.CommandText=查询;
使用(reader=cmd.ExecuteReader())
{
返回读取器;
}
}
}
}
捕获(MySqlException-ex)
{
//哎呀。
}
返回读取器;
}

这种尝试的问题是
读取器从方法返回时关闭

您是否考虑过使用?我喜欢你和我自己,但有很多。而且也是流行的微软解决方案


有了这些工具,您的查询就变成了非常简单的CRUD方法调用,可以(主要)为您进行连接和会话处理。

为什么要从该方法返回datareader?使用
块将其包裹在
内后,它将关闭。另外,您只能在获得
IDbCommand
的实例后才能分配参数,因此我已使用
块将该部分移动到
的内部

如果您严格希望返回datareader,那么最好使用
yield
关键字返回
IEnumerable

private IEnumerable<IDataRecord> RunSqlQuery(string query, 
                                             Dictionary<string, string> queryParms)
{
    using (var dbConn = new MySqlConnection(config.DatabaseConnection))
    {
        using (var cmd = dbConn.CreateCommand())
        {
            if (queryParms.Count > 0)
            {
                // Assign parameters
            }
            cmd.CommandText = query;
            cmd.Connection.Open();
            using (var reader = cmd.ExecuteReader())
                foreach (IDataRecord record in reader as IEnumerable)
                    yield return record;
        }
    }
}
private IEnumerable RunSqlQuery(字符串查询,
字典(查询武器)
{
使用(var dbConn=newmysqlconnection(config.DatabaseConnection))
{
使用(var cmd=dbConn.CreateCommand())
{
如果(queryparts.Count>0)
{
//指定参数
}
cmd.CommandText=查询;
cmd.Connection.Open();
使用(var reader=cmd.ExecuteReader())
foreach(读卡器中的IDataRecord记录为IEnumerable)
收益回报记录;
}
}
}

或者更好的方法是读取数据并返回数据。这样,您就不必依赖db类之外的db名称空间中的类

我一直在走那条路。按照建议ORMs的思路,我首先推荐EF代码。很抱歉,有点离题了,但在第一次使用EF代码之后,我从未想过要回到这个模式

在代码优先之前,EF是一个相当痛苦的问题,但现在它已经成熟,如果你有一个DB,你就有可能修改结构,即一个新的应用程序功能需要一个新的表或列,那么EF代码优先的方法是我的建议。如果是第三方数据库或其他应用程序的数据库,由其他人管理其结构,那么您只需要在他们部署更改时刷新数据模型,那么我不会首先使用代码,而只使用传统的EF,您可以根据一些现有数据库生成/更新模型

using (var dbConn = new MySqlConnection(config.DatabaseConnection))
{
    using (var cmd = dbConn.CreateCommand())
    {
        dbConn.Open();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT version() as Version";

        using (IDataReader reader = cmd.ExecuteReader())
        {
            if (reader.Read())
            {
                Console.WriteLine("Database Version: " + reader.GetString(reader.GetOrdinal("Version")));
            }
        }
    }
}
注意,您可以采用EF并开始使用它,同时保持现有的代码基础不变。这取决于您的框架在多大程度上依赖于使用ADO对象。EF电动工具扩展有一种生成代码优先模型的方法,或者您可以使用传统的非代码优先EF从数据库生成模式

using (var dbConn = new MySqlConnection(config.DatabaseConnection))
{
    using (var cmd = dbConn.CreateCommand())
    {
        dbConn.Open();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "SELECT version() as Version";

        using (IDataReader reader = cmd.ExecuteReader())
        {
            if (reader.Read())
            {
                Console.WriteLine("Database Version: " + reader.GetString(reader.GetOrdinal("Version")));
            }
        }
    }
}
当您想要查询时,您可以直接进入您想要查询的业务,而无需大量的基础结构代码或包装。关于上述包装器的另一件事是,在一些边缘情况下,您必须重新使用ADOAPI而不是RunSqlQuery助手

这是一个很小的例子,因为通常我没有像GetActivePeopleNames这样的方法,只是将查询放在需要的地方。在松散的代码方面几乎没有开销,因此在所有其他代码中使用我的查询不会显得太突兀。虽然我确实练习了一些presenter模式,以从业务逻辑中抽象查询和数据转换

HREntities db = new HREntities();

private ICollection<string> GetActivePeopleNames()
{      
  return db.People.Where(p => p.IsActive).Select(p => p.FirstName + " " + p.LastName)
    .ToList();
}
HREntities db=新的HREntities();
私有ICollection GetActivePeopleNames()
{      
返回db.People.Where(p=>p.IsActive)。选择(p=>p.FirstName+“”+p.LastName)
.ToList();
}
我不必创建参数对象。我本可以为
使用一些变量,其中(p=>p.IsActive==someBool)
,在这种情况下,SQL注入是安全的。连接是自动处理的。我可以使用.Include在同一个c语言中获取相关对象
RunSqlQuery("SELECT * FROM ...", reader => ReadResult(reader));

private bool ReadResult(MySqlDataReader reader)
{
    //Use the reader to read the result

    if (!success)
        return false;

    return true;
}
private bool RunSqlQuery(string query, Func<MySqlDataReader, bool> readerAction)
{
    Dictionary<string, string> queryParms = new Dictionary<string, string>();
    return RunSqlQuery(query, readerAction, queryParms);
}

private bool RunSqlQuery(string query, Func<MySqlDataReader, bool> readerAction, Dictionary<string, string> queryParms)
{
    MySqlDataReader reader = null;
    if (queryParms.Count > 0)
    {
        // Assign parameters
    }

    try
    {
        using (var dbConn = new MySqlConnection(config.DatabaseConnection))
        {
            using (var cmd = dbConn.CreateCommand())
            {
                dbConn.Open();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = query;

                using (reader = cmd.ExecuteReader())
                {
                    return readerAction.Invoke(reader);
                }
            }
        }
    }
    catch (MySqlException ex)
    {
        // Oops.
        return false;
    }
}