无法从字符串中删除撇号以使 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。我尝试了我能想象的一切:
- 我尝试将 ' 替换为 string.empty
- 试图替换为“”
- 甚至尝试替换为“''”(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;
}
}
显然您的代码比您提供的示例更复杂,但这是一个起点。
我正在做一个项目,我在字符串中使用 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。我尝试了我能想象的一切:
- 我尝试将 ' 替换为 string.empty
- 试图替换为“”
- 甚至尝试替换为“''”(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;
}
}
显然您的代码比您提供的示例更复杂,但这是一个起点。