Generate a string like a WHERE statement by a dictionary

廉价感情. 提交于 2019-12-24 09:39:55

问题


I know we should never do this:

string select = "SELECT * FROM table1 ";
string where = "WHERE Name = '" + name + "' ";
string sql = select + where;
//execute the sql via ADO.NET

because of sql injection, because name can contain the char ', because of another 100 reasons. But now I have to do something similiar. I have a Dictionary<string, object> whose data look like:

   Key(string)      Value(object)
    "Name"              "Bob"            //string
    "ID"              10092L             //long 
    "Birthday"      1980-05-07 00:00:00  //DateTime
    "Salary"          5000.5m            //decimal
//some others, whose key is a string, and value is string/long/int/DateTime/decimal

I want an easy way, to get all items in the dictionary collected in a String, just like a where statement:

Name = 'Bob' and ID = 10092 and Birthday = '1980-05-07 00:00:00' and Salary = 5000.5

String and DateTime are quoted with ', but note that the Name can be O'Neal. Is there any easy implementation? Input the dictionary, and return the string as a result.

EDIT Note that what I want is the string, I'm not going to execute it, parameterized command doesn't help. I just want a string that looks like a perfect safe WHERE statement.


回答1:


The first code is only a problem if name is something entered by the user. Otherwise, it should be fine.

I don't know that it eliminates all problems but you might try experimenting with something like name = name.Replace("'", "''"). By converting all single quotes to double single quotes, you prevent the type of problems you described. Another approach might be to remove any single quotes.

However, the best route is to use query arguments. ADO supports these nicely and that would also eliminate any possibility of injection attacks.




回答2:


The easy way could be like this:

string results = string.Join(" and ", myDict.Select( x=> x.Key + " = " +  x.Value)); 

This of course wouldn't solve the quotes ' issue depending on different datatypes so you cannot use this as input to a SQL query - for that I would strongly recommend named parameters anyway - but is otherwise correct depending on the ToString() implementation of the values in your dictionary.




回答3:


I wrote this many years ago, and always use it, and never ever have to think about this again. it is a waste of brain cells to solve this more than once:

        //   replace things like:
    //         O'Keefe     with
    //          'O''Keefe'
    //   make sure you don't call this twice!
    static public string SqlString(string strInputSQL)
    {
        string strOut;
        strOut = strInputSQL;
        strOut = strOut.Replace ("'", "''");
        strOut = "'" + strOut + "'";
        return strOut;
    }

Use it like this:

string sql = "SELECT * FROM FOO WHERE Name LIKE " + SqlString(myvalue);

There may be a dozen other ways to do it, but if you can have one and only one function, and use it consistently, you will save alot of time.




回答4:


Try this link : Creating safe SQL statements as Strings

Some people consider this over-engineered, or just labourious to type. I fall back on a simple argument though...

Someone has already invested time and effort ensuring arguements can be safely and reliably included in SQL statements. Are you 100% certain you have pre-empted every possible scenario? Or is it more likely tried and tested code is more reliable?

But, then, I'm a bit anal ;)




回答5:


var sb = new StringBuilder();
var isFirst = true;
foreach (var element in dic)
{
    if(!isFirst)
        sb.Append(" AND ");
    else
        isFirst = false;
    sb.Append(element.Key);
    sb.Append(" = ");
    if(element.Value is decimal)
      sb.Append(CastToSqlDecimalString((decimal)element.Value));
    else
      sb.Append("'" + String.Format(CultureInfo.InvariantCulture, "{0:G}", element.Value).Replace("'", "''") + "'");
}

You might want to handle decimals using this function

 public static string CastToSqlDecimalString(decimal dec)
        {
            var sqlDecimal = new System.Data.SqlTypes.SqlDecimal(dec);
            return string.Format("CAST({0} AS DECIMAL({1}, {2}))",
                        string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:G}", dec),
                        sqlDecimal.Precision,
                        sqlDecimal.Scale);
        }


来源:https://stackoverflow.com/questions/5393092/generate-a-string-like-a-where-statement-by-a-dictionary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!