2009-11-13 12 views

Respuesta

15
var inClause = "(" 
    + String.Join(",", values.Select(x => x.ToString()).ToArray()) 
    + ")"; 

Nota: Ya no es necesario llamar a .ToArray() en .NET Framework 4. Se añade un nuevo método String.Join<T>(string separator, IEnumerable<string> values).

+0

que producirá una lista , no es una cadena que se puede utilizar en una instrucción SQL – thecoop

+0

thecoop: no he entendido bien su pregunta. Actualizado. –

+0

@thecoop: No, no lo hará. @Mehrdad: No compilará; 'String.Join' solo toma una matriz. – SLaks

5

Si usted no tiene acceso a los métodos de extensión .NET 3.5, se puede hacer esto:

StringBuilder sb = new StringBuilder(); 
sb.Append('('); 

foreach (int i in values) { 
    sb.Append(i).Append(','); 
} 

// remove final , 
sb.Length -= 1; 
sb.Append(')'); 

string inValue = sb.ToString(); 

trabajo Which'll en .NET 2

+0

puedo preguntar lo que los downvotes eran para? – thecoop

4

Usted puede utilizar el método String.Join, como esta:

var str = "(" + string.Join(", ", Array.ConvertAll(values, v => v.ToString(CultureInfo.InvariantCulture))); 

Suponiendo que values es una matriz, Array.ConvertAll debería ser más eficiente que LINQ con ToArray.

2

Esto podría hacerse en una línea demasiado

public string ToInStatement(this int[] values) { 
    string[] stringValues = 
     Array.ConvertAll<int, string>(values, Convert.ToString); 
    string result = "(" + String.Join(",", stringValues) + ")"; 
    return result; 
} 
0

Hey, sugerencias, sólo una ligera modificación a continuación

public static class IEnumerableExtensions 
{ 
    // reasonable to assume you will use this everywhere, not just 
    // Sql statements, but log statements, anywhere you need to 
    // dump a list into a readable format! 
    // 
    // HINT: extra credit: you can generalize this, and provide 
    // specialized short hands that invoke the general method 
    public static string ToCommaSeparatedString<T>(this IEnumerable<T> values) 
    { 
     // SIGH: so apparently this does not generate minimal 
     // assembler on every machine, please note the following 
     // is written for clarity, please feel free to substitute 
     // your own favourite ultra-performance high-octance 
     // string appender algorithm 
     StringBuilder commaSeparated = new StringBuilder(); 
     foreach (T value in values) 
     { 
      // PERF: store format string as const 
      commaSeparated.AppendFormat ("{0}, ", value); 
     } 
     // PERF: store trim chars as static readonly array 
     return commaSeparated.Trim (", ".ToCharArray()); 
    } 
} 

... 
// elsewhere in code 
List<int> myIdentifiers = new List<int> { 1, 2, 3, 4, 5, }; 
string mySqlIdentifierList = myIdentifiers.ToCommaSeparatedList(); 
string mySqlStatementFormat = "SELECT * FROM [SomeTable] WHERE [Id] IN ({0})"; 
string mySqlStatement = 
    string.format (mySqlStatementFormat, mySqlIdentifierList); 
... 
+1

Sería más rápido que llamar dos veces y no anexar analizar la cadena de formato cada vez. También sería más rápido para comprobar si usted está haciendo el primer elemento y, si es así, no agregue la coma. – SLaks

0

Para ello, puede utilizar de manera más eficiente el siguiente método de extensión:

///<summary>Appends a list of strings to a StringBuilder, separated by a separator string.</summary> 
    ///<param name="builder">The StringBuilder to append to.</param> 
    ///<param name="strings">The strings to append.</param> 
    ///<param name="separator">A string to append between the strings.</param> 
    public static StringBuilder AppendJoin(this StringBuilder builder, IEnumerable<string> strings, string separator) { 
     if (builder == null) throw new ArgumentNullException("builder"); 
     if (strings == null) throw new ArgumentNullException("strings"); 
     if (separator == null) throw new ArgumentNullException("separator"); 

     bool first = true; 

     foreach (var str in strings) { 
      if (first) 
       first = false; 
      else 
       builder.Append(separator); 

      builder.Append(str); 
     } 

     return builder; 
    } 

    ///<summary>Combines a collection of strings into a single string.</summary> 
    public static string Join<T>(this IEnumerable<T> strings, string separator, Func<T, string> selector) { return strings.Select(selector).Join(separator); } 
    ///<summary>Combines a collection of strings into a single string.</summary> 
    public static string Join(this IEnumerable<string> strings, string separator) { return new StringBuilder().AppendJoin(strings, separator).ToString(); } 
0
/// <summary> 
/// Converts an array of integers into a string that may be used in a SQL IN expression. 
/// </summary> 
/// <param name="values">The array to convert.</param> 
/// <returns>A string representing the array as a parenthetical comma-delemited list. If the array 
/// is empty or missing, then "(null)" is returned.</returns> 
public static string ToSqlInList(int[] values) 
{ 
    if (values == null || values.Length == 0) 
     return "(null)"; // In SQL the expression "IN (NULL)" is always false. 

    return string.Concat("(", string.Join(",", Array.ConvertAll<int, string>(values,x=>x.ToString())), ")"); 
} 
1

Si su lista de enteros es grande, puede terminar generando una cadena demasiado larga para que la base de datos la acepte. P.ej. Creo que la longitud máxima de un VARCHAR en SQL2000 es de alrededor de 8K.

Así que tienen un conjunto de método de ayuda algo así como el ejemplo siguiente, que devuelve una enumeración de cadenas, que luego pueden ser utilizados de la siguiente manera:

List<int> idList = ...; 
using(SqlCommand command = ...) 
{ 
    ... 
    foreach(string idString in ConcatenateValues(ids,",", maxLength, false)) 
    { 
     command.Parameters[...] = idString; 
     // or command.CommandText = "SELECT ... IN (" + idString + ")..."; 
     ... execute command ... 
    } 
} 

El método de concatenación podría ser algo como lo siguiente:

public static IEnumerable<string> ConcatenateValues(IEnumerable<int> values, string separator, int maxLength, bool skipDuplicates) 
{ 
    IDictionary<int, string> valueDictionary = null; 
    StringBuilder sb = new StringBuilder(); 
    if (skipDuplicates) 
    { 
     valueDictionary = new Dictionary<int, string>(); 
    } 
    foreach (int value in values) 
    { 
     if (skipDuplicates) 
     { 
      if (valueDictionary.ContainsKey(value)) continue; 
      valueDictionary.Add(value, ""); 
     } 
     string s = value.ToString(CultureInfo.InvariantCulture); 
     if ((sb.Length + separator.Length + s.Length) > maxLength) 
     { 
      // Max length reached, yield the result and start again 
      if (sb.Length > 0) yield return sb.ToString(); 
      sb.Length = 0; 
     } 
     if (sb.Length > 0) sb.Append(separator); 
     sb.Append(s); 
    } 
    // Yield whatever's left over 
    if (sb.Length > 0) yield return sb.ToString(); 
} 
+0

No está poniendo la cuerda en una columna; él está construyendo una cláusula 'IN'. Lea la pregunta. – SLaks

+0

Esta técnica también se puede usar para una cláusula IN. – Joe

Cuestiones relacionadas