C# 使用通用字典向表中插入值
编码平台:ASP.NET 2.0 WebForms,以C#和MySQL为后端 背景 我目前正在修复一个网站的bug。C# 使用通用字典向表中插入值,c#,asp.net,architecture,data-structures,data-access,C#,Asp.net,Architecture,Data Structures,Data Access,编码平台:ASP.NET 2.0 WebForms,以C#和MySQL为后端 背景 我目前正在修复一个网站的bug。 其中一个表“registrations”有80列 插入/更新是通过简单的sql语句完成的,没有任何参数化查询 问题 在注册时,用户可以改变许多参数,从而产生至少15种插入查询。我的问题是如何确保所有字段都插入了正确的值 所以,我创建了一个 Dictionary<string, string> fields = new Dictionary<string, str
其中一个表“registrations”有80列 插入/更新是通过简单的sql语句完成的,没有任何参数化查询 问题 在注册时,用户可以改变许多参数,从而产生至少15种插入查询。我的问题是如何确保所有字段都插入了正确的值 所以,我创建了一个
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("LoginEmail", MySQL.SingleQuoteSQL(txtLoginEmail.Text));
fields.Add("Password", MySQL.SingleQuoteSQL(txtLoginPassword.Text));
fields.Add("ContactName", MySQL.SingleQuoteSQL(txtContactName.Text));
fields.Add("City", MySQL.SingleQuoteSQL(txtCity.Text));
我的问题是
字符串列表(IEnumerable enumerable)
string list<T>(IEnumerable<T> enumerable)
{
List<T> list = new List<T>(enumerable);
return string.Join(",", list.ToArray());
}
//...
string sql= String.Format("INSERT INTO registrations({0}) VALUES({1})",
list(fields.Keys),
list(fields.Values));
{
列表=新列表(可枚举);
返回字符串.Join(“,”,list.ToArray());
}
//...
string sql=string.Format(“插入到注册({0})值({1})”,
列表(字段、键),
列表(字段.值));
我知道描述中说您没有使用参数化sql,但是我知道,使用参数化sql是防止sql注入的更好方法。在txtLoginEmail中加入一些SQL并提交表单,对您的情况造成严重破坏,这根本不需要花费太多精力
private static string CreateInsertSql(string table,
IDictionary<string, string> parameterMap)
{
var keys = parameterMap.Keys.ToList();
// ToList() LINQ extension method used because order is NOT
// guaranteed with every implementation of IDictionary<TKey, TValue>
var sql = new StringBuilder("INSERT INTO ").Append(table).Append("(");
for (var i = 0; i < keys.Count; i++)
{
sql.Append(keys[i]);
if (i < keys.Count - 1)
sql.Append(", ");
}
sql.Append(") VALUES(");
for (var i = 0; i < keys.Count; i++)
{
sql.Append('?').Append(keys[i]);
if (i < keys.Count - 1)
sql.Append(", ");
}
return sql.Append(")").ToString();
}
私有静态字符串CreateInsertSql(字符串表,
IDictionary参数映射)
{
var keys=parameterMap.keys.ToList();
//使用ToList()LINQ扩展方法,因为顺序不是
//每一个IDictionary实现都有保证
var sql=newstringbuilder(“插入”).Append(表).Append(“”);
对于(变量i=0;i我认为字典结构在这种情况下是可以的,但是 按原样构建和执行字符串允许SQL注入数据包 xkcd.com/327/利用妈妈 我正在使用.NET3.5,但这个想法也可以应用于.NET2.0 如果MySQL.SingleQuoteSQL做的比它的名字建议的更多,那么请让我知道 否则,将这些值添加为参数以防止出现这种情况
var values = new Dictionary<string, string>() {
{"LoginEmail", "LoginEmail"},
{"Password", "Password"},
{"ContactName", "ContactName"},
{"City", "City"}
};
System.Func<string, string> key = p => String.Concat("?", p);
var statement = string.Format("INSERT INTO registrations ({0}) VALUES ({1})",
string.Join(",", values.Values.ToArray()),
string.Join(",", values.Keys.Select(key).ToArray())
);
//"INSERT INTO registrations (LoginEmail,Password,ContactName,City) VALUES (?LoginEmail,?Password,?ContactName,?City)"
foreach(var p in values) {
command.Parameters.Add(key(p.Key), p.Value, SqlDbType.Text);
}
command.Prepare();
command.ExecuteNonQuery();
They may be other better classes for .NET mysql, apologies if so - I haven't used mysql in .NET
var值=新字典(){
{“LoginEmail”,“LoginEmail”},
{“密码”,“密码”},
{“ContactName”,“ContactName”},
{“城市”,“城市”}
};
System.Func key=p=>String.Concat(“?”,p);
var语句=string.Format(“插入到注册({0})值({1})”,
string.Join(“,”,values.values.ToArray()),
string.Join(“,”,values.Keys.Select(key.ToArray())
);
//“在注册(登录邮箱、密码、联系人姓名、城市)中插入值(?登录邮箱、密码、联系人姓名、城市)”
foreach(值中的var p){
Add(key(p.key)、p.Value、SqlDbType.Text);
}
command.Prepare();
command.ExecuteNonQuery();
对于.NET mysql,它们可能是其他更好的类,如果是的话,很抱歉-我在.NET中没有使用mysql
是的,键
中键的顺序与值
中相关值的顺序相同。请参阅.NET 4.0中的“备注”。我已更新了.NET 3.5的答案(使用System.Linq;
)@mark:非常感谢,我最终在每个keyvaluepair上使用了foreach,并将键/值存储在两个数组中。在值中添加任何错误的charter都将导致错误,并且它将成为SQL注入的目标。谢谢。您的第一个函数可以在一行中编写。请参阅marks代码。此外,我使用的是C#2.0 True,但它的效率不如代码所使用的那么高s 2个StringBuilder实例(每个string.Join调用中有1个)和4个串联,在内存中创建3个不必要的字符串。我的使用单个StringBuilder创建0个不必要的字符串。此外,您不能使用string.Join在所有参数名称前面加上分隔符(?,在本例中)。抱歉,内存中有5个不必要的字符串,因为我忘记了字符串的结果字符串。Join calls。抱歉..死马。我认为这是避免SQL注入的最佳解决方案,但只有当您将Append(“?”)更改为Append(“@”)时,它才起作用。…好工作MySQL.SingleQuoteSQL注释所有单引号
SqlInsert("registrations", new Dictionary<string, string>()
{
{ "LoginEmail", txtLoginEmail.Text },
{ "Password", txtLoginPassword.Text },
{ "ContactName", txtContactName.Text },
{ City", txtCity.Text }
});
var values = new Dictionary<string, string>() {
{"LoginEmail", "LoginEmail"},
{"Password", "Password"},
{"ContactName", "ContactName"},
{"City", "City"}
};
System.Func<string, string> key = p => String.Concat("?", p);
var statement = string.Format("INSERT INTO registrations ({0}) VALUES ({1})",
string.Join(",", values.Values.ToArray()),
string.Join(",", values.Keys.Select(key).ToArray())
);
//"INSERT INTO registrations (LoginEmail,Password,ContactName,City) VALUES (?LoginEmail,?Password,?ContactName,?City)"
foreach(var p in values) {
command.Parameters.Add(key(p.Key), p.Value, SqlDbType.Text);
}
command.Prepare();
command.ExecuteNonQuery();
They may be other better classes for .NET mysql, apologies if so - I haven't used mysql in .NET