C# 动态生成SQL查询

C# 动态生成SQL查询,c#,sql,winforms,C#,Sql,Winforms,我根据用户输入动态创建文本框,如下所示: int nbrTextBoxBE = int.Parse(textBoxNbrBE.Text); panelBE.Controls.Clear(); panelBE.Focus(); for (int i = 0; i < nbrTextBoxBE; i++) { TextBox textBoxArticleCodeBE = new TextBox(); TextBox textBoxDesignationBE = new Text

我根据用户输入动态创建文本框,如下所示:

int nbrTextBoxBE = int.Parse(textBoxNbrBE.Text);
panelBE.Controls.Clear();
panelBE.Focus();
for (int i = 0; i < nbrTextBoxBE; i++)
{
    TextBox textBoxArticleCodeBE = new TextBox();
    TextBox textBoxDesignationBE = new TextBox();
    textBoxCArticleCodeBE.Name = "ArticleCodeBE" + (i + 1);
    textBoxDesignationBE.Name = "DesignationBE" + (i + 1);
    textBoxArticleCodeBE.Text = "";
    textBoxDesignationBE.Text = "";
    panelBE.Controls.Add(textBoxArticleCodeBE);
    panelBE.Controls.Add(textBoxDesignationBE);
    panelBE.Show();
}
我尝试使用foreach循环来实现这一点:

foreach (TextBox tb in panelBE.Controls.OfType<TextBox>())
{
    // do stuff 
}
foreach(panelBE.Controls.OfType()中的文本框tb)
{
//做事
}
当然,它生成的查询数量是我需要的两倍。

在这种情况下,虽然不是最干净的解决方案,但您可以通过正常的
for
循环轻松实现这一点

var textboxes = panelBE.Controls.OfType<TextBox>();
for(int i=0; i < textboxes.length; i+=2)
{
   var articleCodeTextbox = textboxes[i];
   var designationCodeTextbox = textboxes[i+1];
   //build your query
}
然后,您可以简单地循环所有属于
ArticleCodeBE
textbox的文本框,然后您可以像这样从字典中拉出附带的
designationdebe
textbox:

Dictionary<TextBox, TextBox> Textboxes = new Dictionary<TextBox, TextBox>();

int nbrTextBoxBE = int.Parse(textBoxNbrBE.Text);
panelBE.Controls.Clear();
panelBE.Focus();
for (int i = 0; i < nbrTextBoxBE; i++)
{
    TextBox textBoxArticleCodeBE = new TextBox();
    TextBox textBoxDesignationBE = new TextBox();
    textBoxCArticleCodeBE.Name = "ArticleCodeBE" + (i + 1);
    textBoxDesignationBE.Name = "DesignationBE" + (i + 1);
    textBoxArticleCodeBE.Text = "";
    textBoxDesignationBE.Text = "";
    panelBE.Controls.Add(textBoxArticleCodeBE);
    panelBE.Controls.Add(textBoxDesignationBE);
    Textboxes.Add(textBoxArticleCodeBE, textBoxDesignationBE);
    panelBE.Show();
}
foreach (TextBox articleCodeTB in panelBE.Controls.OfType<TextBox>().Where(tb => tb.Name.Contains("ArticleCodeBE")))
{
     var designationCodeTB = TextBoxes[articleCodeTB];
     //build your query  
}
foreach(panelBE.Controls.OfType()中的文本框articleCodeTB,其中(tb=>tb.Name.Contains(“ArticleCodeBE”))
{
var designationcodeb=文本框[articleCodeTB];
//构建您的查询
}

在这种情况下,更好的解决方案是使用专用控件按照适当的viewmodel方向执行某些操作。您不必再担心如何匹配文本框。

完成任务的最正确方法是使用参数集合

// This is assumed to be even
TextBox[] txtArray = panelBE.Controls.OfType<TextBox>().ToArray();

for(int x = 0; x < txtArray.Length; x+=2)
{
    TextBox tArticle = txtArray[x];
    TextBox tDesignation = txtArray[x+1];

    // Where you build the query text
    StringBuilder sb = new StringBuilder();

    // The placeholders for the parameters to be used
    List<string> prmNames = new List<string>();

    // The parameter collection 
    List<SqlParameter> prms = new List<SqlParameter>();

    // Initial text for the query
    sb.Append("INSERT INTO myTable (ArticleCode, Designation) VALUES (");

    prmNames.Add("@p" + tArticle.Name);
    prms.Add(new SqlParameter() 
    {
        ParameterName = "@p" + tArticle.Name,
        SqlDbType = SqlDbType.NVarChar,
        Value = tArticle.Text
    });
    prmNames.Add("@p" + tDesignation.Name);
    prms.Add(new SqlParameter()
    {
         ParameterName = "@p" + tDesignation.Name,
         SqlDbType = SqlDbType.NVarChar,
         Value = tDesignation.Text
    });

    // Concat the parameters placeholders and close the query text
    sb.Append(string.Join(",", prmNames) + ")");

    // Pass everything to an utility method
    // This could be part of a bigger utility database class
    ExecuteInsertInto(sb.ToString(), prms);
}
还有一种更好的方法,可以通过对ExecuteInsertInto的单个调用来传递每个命令,但确切的语法取决于数据库类型。简而言之,您可以构建一个包含多个插入的查询文本。有关Sql Server,请参阅 那怎么样:

foreach (TextBox tb in this.Controls.OfType<TextBox>().Where(textbox => textbox.Name.StartsWith("DesignationBE")))
{
    //do stuff
}
foreach(this.Controls.OfType()中的TextBox tb,其中(TextBox=>TextBox.Name.StartsWith(“DesignationBE”))
{
//做事
}

增量需要是
i+=2
,而不是
i++
。这也取决于
文本框
列表与添加文本框的顺序完全相同。这很可能是事实,但不能保证是相同的。@关于编辑文本框的顺序更为平坦;我已经提到:)参数化查询的荣誉。你在这里写了半个DAL只是为了解释这个概念。起初我认为你的答案是正确的,但后来我注意到它会生成一个SQL,看起来像这样:
插入myTable(ArticleCode,Designation)值(@ArticleCodeBE1,@DesignationBE1,@ArticleCodeBE2,@DesignationBE2,@ArticleCodeBEn,@DesignationBEn)
。。。你需要一个稍微不同的代码来创建
值(@p1,p2),(@p3,@p4).
@Steve我试图运行你的代码,但它在使用Append()和Add()方法时返回错误<代码>错误5方法“Add”的无重载包含2个参数和
错误2“System.Collections.Generic.List”不包含“Append”的定义,并且找不到接受类型为“System.Collections.Generic.List”的第一个参数的扩展方法“Append”(是否缺少using指令或程序集引用?)
我认为对于调用方和被调用方来说,
params SqlParameter[]params
List prms=null
要好得多。@A.Petit让我在Visual Studio中重写整个过程。如果您不手工编写此代码,您永远不会对Intellisense有足够的欣赏。您正在使用哪些rdbms?
private int ExecuteInsertInto(string query, List<SqlParameter> prms = null)
{
   using(SqlConnection cnn = new SqlConnection(..connectionstring goes here..))
   using(SqlCommand cmd = new SqlCommand(query))
   {
        cnn.Open();
        if(prms != null)
            cmd.Parameters.AddRange(prms.ToArray());
        return cmd.ExecuteNonQuery();
   }
}
  string fieldName = tb.Text.Substring(0, tb.Text.IndexOf("BE"));
foreach (TextBox tb in this.Controls.OfType<TextBox>().Where(textbox => textbox.Name.StartsWith("DesignationBE")))
{
    //do stuff
}