2013-11-22 78 views
5

我需要以下查詢:的SqlParameter並在聲明

createList(string commaSeparatedElements) { 
    ... 
    SqlCommand query = new SqlCommand("SELECT * FROM table WHERE id IN ("+commaSeparatedElements+")"); 
    ... 
} 

我想使用參數化查詢來寫,所以從字符串中的每個元素進行檢查,以防止對SQL的注射。

僞代碼:

createList(string commaSeparatedElements) { 
    ... 
    SqlParameterList elements = new SqlParameterList("@elements", SqlDbType.Int); 
    SqlParameterList.Values = commaSeparatedElements.split(new Char[1] {','}); 
    SqlCommand query = new SqlCommand("SELECT * FROM table WHERE id IN (@elements)"); 
    query.Parameters.Add(elements); 
    ... 
} 

難道這樣的事情在C#中存在,否則我將不得不由我自己寫呢?

編輯:感謝所有的答案。由於我儘量不使用代碼,我不明白(在過去的日子裏有太多不好的經歷),即使它們可能完美滿足我的需求,但是精簡和表值參數都是禁止的。我剛剛做了一個循環。

string[] elements = commaSeparatedElements.split(new Char[1] {','}); 
StringList idParamList = new StringList(); 
for(int i=0;i<elements.Count;i++) { 
    query.Parameters.AddWithValue("@element"+i,Convert.ToInt32(elements[i])); 
    idParamList.Add("@element" + i); 
} 
SqlCommand query = new SqlCommand("SELECT * FROM table WHERE id IN ("+String.Join(",",idParamList)+")"); 
+1

自己寫吧 –

+0

[檢查此](http://stackoverflow.com/questions/4502821/how-do-i-translate-a-liststring-into-a-sqlparameter-for-a-sql-in-statement ) –

回答

1

我使用這樣

/// <summary> 
/// Adds a sequence of parameters to an existing parameter collection 
/// </summary> 
/// <typeparam name="T">Type of parameter values</typeparam> 
/// <param name="parameters">Existing parameter collection</param> 
/// <param name="pattern">Name pattern of parameters. Must be a valid <see langword="int"/> format string</param> 
/// <param name="parameterType">Database type of parameters</param> 
/// <param name="length">Length of parameter. 0 for numeric parameters</param> 
/// <param name="values">Sequence of values</param> 
/// <returns>Comma separated string of parameter names</returns> 
public static string AddParameters<T>(SqlParameterCollection parameters, 
             string pattern, 
             SqlDbType parameterType, 
             int length, 
             IEnumerable<T> values) { 
    if (parameters == null) 
     throw new ArgumentNullException("parameters"); 
    if (pattern == null) 
     throw new ArgumentNullException("pattern"); 
    if (values == null) 
     throw new ArgumentNullException("values"); 
    if (!pattern.StartsWith("@", StringComparison.CurrentCultureIgnoreCase)) 
     throw new ArgumentException("Pattern must start with '@'"); 

    var parameterNames = new List<string>(); 
    foreach (var item in values) { 
     var parameterName = parameterNames.Count.ToString(pattern, CultureInfo.InvariantCulture); 
     parameterNames.Add(parameterName); 
     parameters.Add(parameterName, parameterType, length).Value = item; 
    } 

    return string.Join(",", parameterNames.ToArray()); 
} 

它用於像一個輔助方法這

string sql = "SELECT col1 " + 
      "FROM Table " + 
      "WHERE col2 IN ({@Values}) "; 
var paramNames = SqlHelper.AddParameters(command.Parameters, 
             "@Value0", 
             SqlDbType.Int, 
             0, 
             listOfInts); 
command.CommandText = sql.Replace("{@Values}", paramNames); 
... 

(結果就像SELECT ... IN (@Value0, @Value1, @Value2)查詢)

2

如果聲明

List<int> Ids = new List<int>(); 

,並添加有你想要的ID。人們很容易把它轉換的逗號分隔列表如下

string listOfIds = string.Join(",", Ids.Select(Id => Id.ToString()).ToArray()); 

然後,你將這個字符串作爲參數傳遞給你的參數化查詢。

+1

不行,因爲我不喜歡'請問'SELECT * FROM表WHERE id IN(「1,2,3」)',我問'SELECT * FROM表WHERE id IN(1,2,3)' – Alexander

3

SQL Server有一個數據結構,非常適合保存同一個「類型」的多個值 - 這就是一張表。

值得慶幸的是,近年來,他們推出Table-Valued Parameters,這樣就可以構建一個表中您的客戶端代碼,並通過跨到以自然的方式在SQL Server中,如:

// Assumes connection is an open SqlConnection. 
using (connection) 
{ 
// Create a DataTable with the modified rows. 
DataTable addedCategories = CategoriesDataTable.GetChanges(
    DataRowState.Added); 

// Define the INSERT-SELECT statement. 
string sqlInsert = 
    "INSERT INTO dbo.Categories (CategoryID, CategoryName)" 
    + " SELECT nc.CategoryID, nc.CategoryName" 
    + " FROM @tvpNewCategories AS nc;" 

// Configure the command and parameter. 
SqlCommand insertCommand = new SqlCommand(
    sqlInsert, connection); 
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue(
    "@tvpNewCategories", addedCategories); 
tvpParam.SqlDbType = SqlDbType.Structured; 
tvpParam.TypeName = "dbo.CategoryTableType"; 

// Execute the command. 
insertCommand.ExecuteNonQuery(); 
} 
+0

這是最好的方法,但要注意:由於參數嗅探,TVPs可以使用存儲過程。 –

-1

或者你可以把如果條件爲參數。例如:

if(commaSeparatedElements.Contains("'")) 
    return; 
else 
    //Pass parameter & Execute query 
8

"dapper"有一些這方面的巫術:

var ids = new List<int> {1,2,3,4,5}; 
var rows = conn.Query<SomeType>("select * from table where id in @ids", 
     new { ids }).ToList(); 

你會發現不足,在in使用括號的; 「小巧玲瓏」點出這一點,並自動執行參數擴展。此外,它還爲您處理所有命令的詳細信息,包括將數據映射回SomeType實例。

在上面的例子中,將擴大到相當於(約):

int ids0 = 1, ids1 = 2, ids2 = 3, ids3 = 4, ids4 = 5; 
var rows = conn.Query<SomeType>(
    "select * from table where id in (@ids0,@ids1,@ids2,@ids3,@ids4)", 
     new { ids0, ids1, ids2, ids3, ids4 }).ToList(); 
0

這是我一直在做一個項目:

 StringBuilder sb = new StringBuilder("Id IN("); 
     List<SqlParameter> parameters = new List<SqlParameter>(); 
     int i = 1; 

     foreach (int item in items) 
     { 
      string currentItem = "@Item" + i++.ToString(); 
      sb.Append(currentItem + ","); 
      parameters.Add(new SqlParameter(currentItem , item)); 
     } 
     sb.Remove(sb.Length-1, 1); 

     sb.Append(")"); 

我希望這有助於