2010-02-22 10 views
1

J'ai besoin d'ajouter une requête SQL pour chaque ligne dans un datatable.J'ai 36 colonnes et en fonction du type de données de chaque colonne, je dois ajouter sqlquery.Can quelqu'un me suggère le moyen efficace de le faire.Il c'est une mauvaise façon de coder pour utiliser l'opérateur "+" pour ajouter du texte entre les append?Utilisation efficace de StringBuilder

Following is my code. 

query ="INSERT INTO MASTERPI (tag,instrumenttag)"); 
query += "VALUES ('" + createTagRow["tag"].ToString() + "','" + createTagRow["instrumenttag"].ToString() + "'"); 

Merci, Vix

+2

Mes yeux ... les lunettes ne font rien! – Aaronaught

+0

oh man. Comment avez-vous fait cela ?? tester les limites de StringBuilder !! –

Répondre

0

Votre code serait probablement plus lisible si vous avez utilisé String.Format pour construire chaque ligne de la requête, en utilisant la syntaxe de l'espace réservé pour interpoler les données de votre objet ligne dans la texte de requête.

+0

Performance-sage, ce n'est pas beaucoup mieux que la concaténation. Vous créez toujours un tas d'instances 'string' jetables au lieu d'utiliser efficacement' StringBuilder'. – Aaronaught

+0

Je suggérerais que vous créiez également une méthode d'extension pour gérer la concaténation de chaîne, simplement à partir d'une perspective de lisibilité de code en conjonction avec la réponse ci-dessus. – Ahmad

+0

@Ahmad: Que fait une méthode d'extension ici? Je voudrais pouvoir rétrograder les commentaires. – Aaronaught

5

Si vous utilisez déjà un StringBuilder, il est préjudiciable d'utiliser une concaténation de chaîne normale en même temps. Vous annulez la moitié de l'utilité de la classe StringBuilder. Ne fais pas ça. Utilisez la méthode StringBuilder.Append exclusive et se débarrasser de ces + instructions.

Je pense également que tous ces appels createTagRow(...).ToString() sont inutiles. Quelque chose dans cette section effectue le travail de sérialisation de ces éléments en une chaîne, de sorte que vous effectuez le travail deux fois, en créant la chaîne et en l'ajoutant ensuite. S'il vous est possible de passer le StringBuilder lui-même à ces appels createTagRow, ce serait également beaucoup moins ... effrayant.

En fait, lors d'un second survol, il semble que ce code construit une requête SQL. Paramétrez cette requête MAINTENANT. Pas d'excuses. De cette façon, vous n'aurez même pas à vous soucier de string.Format par rapport à StringBuilder par rapport à la concaténation, la bibliothèque DB gérera tout pour vous.

+2

+1 pour le paramétrage de la requête - tout autre problème pose problème – Will

0

Comme déjà mentionné, vous devriez envisager deux possibilités:

  1. Aaronaught: Parameterize that query
  2. Si vous avez besoin un contrôle total sur la chaîne d'instruction, vous devriez jeter un coup d'oeil dans .FormatWith extension et factoriser vos différents blocs en classes, qui donnent les pièces nécessaires.

Un petit exemple:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.Web.UI; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var columns = new CommaSeparated(); 

      columns.Add("tag"); 
      columns.Add("instrumenttag"); 
      columns.Add("pointsource"); 
      columns.Add("pointtype"); 
      columns.Add("dataowner"); 
      columns.Add("dataaccess"); 
      columns.Add("location1"); 
      columns.Add("location2"); 
      columns.Add("location3"); 
      columns.Add("location4"); 
      columns.Add("location5"); 
      columns.Add("..."); 


      var values = new CommaSeparated(); 

      values.EncloseEachElementWith = "'"; 
      values.Add(createTagRow["tag"].ToString()); 
      values.Add(createTagRow["instrumenttag"].ToString()); 
      values.Add(createTagRow["pointsource"].ToString()); 
      values.Add(createTagRow["pointtype"].ToString()); 
      values.Add(createTagRow["dataowner"].ToString()); 
      values.Add(createTagRow["dataaccess"].ToString()); 
      values.Add(createTagRow["location1"].ToString()); 
      values.Add(createTagRow["location2"].ToString()); 
      values.Add(createTagRow["location3"].ToString()); 
      values.Add(createTagRow["location4"].ToString()); 
      values.Add(createTagRow["location5"].ToString()); 
      values.Add(createTagRow["..."].ToString()); 

      //INSERT INTO MASTERPI ({columns}) values ({values}) 
      var query = "INSERT INTO MASTERPI ({columns}) values ({values})".FormatWith(new { columns, values }); 

      Console.WriteLine(query); 
      Console.ReadKey(); 
     } 
    } 

    public class CommaSeparated : List<string> 
    { 
     public CommaSeparated() 
      : base() 
     { 
      EncloseEachElementWith = String.Empty; 
     } 

     public override string ToString() 
     { 
      var elements = this.Select(element => String.Format("{0}{1}{0}", EncloseEachElementWith, element)); 

      return String.Join(", ", elements.ToArray()); 
     } 

     public string EncloseEachElementWith { get; set; } 
    } 

    public static class StringExtensions 
    { 
     public static string FormatWith(this string format, object source) 
     { 
      return FormatWith(format, null, source); 
     } 

     public static string FormatWith(this string format, IFormatProvider provider, object source) 
     { 
      if (format == null) 
       throw new ArgumentNullException("format"); 

      Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", 
       RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 

      List<object> values = new List<object>(); 
      string rewrittenFormat = r.Replace(format, delegate(Match m) 
      { 
       Group startGroup = m.Groups["start"]; 
       Group propertyGroup = m.Groups["property"]; 
       Group formatGroup = m.Groups["format"]; 
       Group endGroup = m.Groups["end"]; 

       values.Add((propertyGroup.Value == "0") 
        ? source 
        : DataBinder.Eval(source, propertyGroup.Value)); 

       return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value 
        + new string('}', endGroup.Captures.Count); 
      }); 

      return string.Format(provider, rewrittenFormat, values.ToArray()); 
     } 
    } 
} 
+0

J'essaie d'utiliser string + = comme ceci: query = "INSERT INTO MASTERPI (tag, instrumenttag)"); query + = "VALEURS ('" + createTagRow ["tag"]. ToString() + "'," "+ createTagRow [" instrumenttag "]. ToString() +" '"); Est-ce efficace? – vix

+0

A la question de savoir si c'est efficace, c'est très difficile à lire. Donc, il est inefficace en ce qui concerne la maintenabilité.Mon approche n'est pas tout à fait parfaite, car les deux listes doivent être dans le même ordre. Cela pourrait être réalisé en utilisant une sorte de Tuple , mais cela peut être résolu par le questionneur lui-même. Il devrait seulement montrer une autre approche pour résoudre ce problème. – Oliver