无法从字符串中删除撇号以使 MySQL 查询在 C# 中工作

Cannot delete apostrophe from string to make MySQL query work in C#

我正在做一个项目,我在字符串中使用 mp3 歌曲的元数据 class。这些是我要复制到 mySQL 数据库(来自我根据数据制作的列表)的数据(即艺术家、标题等),我有下一个查询:

SELECT * FROM database.tablename WHERE artist='"+song[i].artist+ "' AND title='" + song[i].title + "' AND genre='"+song[i].genre+"';

代码运行完美(知道成功复制了 12 行),直到 for 循环到达包含撇号 (') 的歌曲,它退出并在给定符号处出现语法错误。例如:song[i].title是I'm not her。我尝试了我能想象的一切:

  1. 我尝试将 ' 替换为 string.empty
  2. 试图替换为“”
  3. 甚至尝试替换为“''”(2 个撇号),以便查询可以识别撇号,但似乎无济于事(总是出现相同的语法错误,就像替换甚至不存在时一样)

这是一行,所以你可以看到我是如何尝试的: song[i].artist = song[i].artist.Replace("'","");

所以我的问题是:有什么解决办法可以去掉撇号,或者有什么方法可以使查询正常工作吗?

编辑:这是我的原始代码(只有 for 循环)以便更好地理解。

for (int i = 0; i < Array.Length; i++)
            {
                Command = @"SELECT * FROM database.tablename WHERE artist='"+song[i].artist+ "' AND title='" + song[i].title + "' AND genre='"+song[i].genre+"';";
                MySqlCommand myCommand = new MySqlCommand(Command);
                using (MySqlConnection mConnection = new MySqlConnection(ConnectionString.ToString()))
                {
                    adapter = new MySqlDataAdapter(Command,mConnection);
                    mConnection.Open();
                    adapter.Fill(dataset);
                    int adat = dataset.Tables[0].Rows.Count;
                    if (adat <= 0)       //if current data does not exist
                    {
                        song[i].artist = song[i].artist.Replace("'","\'");
                        song[i].title = song[i].title.Replace("'", "\'");
                        song[i].genre = song[i].genre.Replace("'", "\'");
                        myCommand = new MySqlCommand("INSERT INTO database.tablename (artist,title,length,genre) VALUES ('"+song[i].artist+"','"+song[i].title+"','"+song[i].length+"','"+song[i].genre+"');",mConnection);
                        myCommand.ExecuteNonQuery();
                        dataset.Clear();
                    }
                    mConnection.Close();
                }
            }

这就是我 "using"(抱歉,不知道如何让它看起来合适):

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using TagLib; using TagLib.Id3v2; using System.Configuration; using System.Data.SqlClient; using MySql; using MySql.Data; using MySql.Data.MySqlClient; using Programname.Properties;

正如@Chad 所提到的,参数是必经之路。

使用标准 System.Data 类,您可能会看到这样的内容:

// set up command using @parameters
using (SqlCommand cmd = new SqlCommand("SELECT * FROM database.tablename WHERE artist=@artist AND title=@title AND genre=@genre", connection))
{
    // add parameter values to command
    cmd.Parameters.Add(new SqlParameter("@artist", song[i].artist));
    cmd.Parameters.Add(new SqlParameter("@title", song[i].title));
    cmd.Parameters.Add(new SqlParameter("@genre", song[i].genre));

    SqlDataReader reader = cmd.ExecuteReader();

    // do useful stuff here
}

我从 here 找到了(然后被砍掉了)一个 MySQL Connector/NET 教程,它可能更 MySQL-具体:

string connStr = "*** your connection string here ***";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();

string sql = "SELECT * FROM database.tablename WHERE artist=@artist AND title=@title AND genre=@genre";
MySqlCommand cmd = new MySqlCommand(sql, conn);

cmd.Parameters.AddWithValue("@artist", song[i].artist);
cmd.Parameters.AddWithValue("@title", song[i].title);
cmd.Parameters.AddWithValue("@genre", song[i].genre);

MySqlDataReader rdr = cmd.ExecuteReader();

// do useful stuff here

rdr.Close();
conn.Close();

只需将与数据提供者无关的解决方案添加到组合中,您就可以采用这种方法将代码与 MySql 分离。

ConnectionString可以在app/web.config:

中设置
<connectionStrings>
  <add name="Example" providerName="MySql.Data.MySqlClient" connectionString="Data Source=1.1.1.1"/>
</connectionStrings>

并且代码将使用 System.Data.Common 类:

var connectionSettings = ConfigurationManager.ConnectionStrings["Example"];
var dbFactory = DbProviderFactories.GetFactory(connectionSettings.ProviderName);

using (DbConnection connection = dbFactory.CreateConnection(connectionSettings.ConnectionString))
using (DbCommand countCommand = connection.CreateCommand())
{
    string sql = @"
SELECT COUNT(*) 
FROM database.tablename 
WHERE artist=@artist AND title=@title 
AND genre=@genre";

    countCommand.CommandText = sql;
    countCommand.Parameters.Add(dbFactory.GetParameter("@artist", null));
    countCommand.Parameters.Add(dbFactory.GetParameter("@title", null));
    countCommand.Parameters.Add(dbFactory.GetParameter("@genre", null));

    for (int i = 0; i < songs.Length; i++)
    {
        var song = songs[i];

        countCommand.Parameters["@artist"].Value = song.artist;
        countCommand.Parameters["@title"].Value = song.title;
        countCommand.Parameters["@genre"].Value = song.genre;

        int matches = (int)countCommand.ExecuteScalar();
        if (matches == 0)
            continue;

        using (DbCommand insertCommand = connection.CreateCommand())
        {
            string insertSql = @"
INSERT INTO database.tablename(artist, title, length, genre) 
VALUES(@artist, @title, @length, @genre";

            insertCommand.CommandText = insertSql;
            insertCommand.Parameters.Add(dbFactory.GetParameter("@artist", song.artist));
            insertCommand.Parameters.Add(dbFactory.GetParameter("@title", song.title));
            insertCommand.Parameters.Add(dbFactory.GetParameter("@length", song.length));
            insertCommand.Parameters.Add(dbFactory.GetParameter("@genre", song.genre));

            int result = insertCommand.ExecuteNonQuery();
        }
    }
}

您还可以创建自定义扩展,提供比 DbProviderFactory:

更好的选项
public static class FactoryExtensions
{
    public static DbParameter GetParameter(this DbProviderFactory factory, string name, object value)
    {
        var param = factory.CreateParameter();
        param.Value = value ?? DBNull.Value;
        param.Name = name;
        return param;
    }

    public static DbConnection CreateConnection(this DbProviderFactory factory, string connectionString, bool open = true)
    {
        DbConnection connection = factory.CreateConnection();
        connection.ConnectionString = connectionString;

        if (open)
            connection.Open();

        return connection;
    }
}

显然您的代码比您提供的示例更复杂,但这是一个起点。