代码之家  ›  专栏  ›  技术社区  ›  thedisplayedName

“当前上下文中不存在名称”TextBox“在一些教程中出现错误

  •  0
  • thedisplayedName  · 技术社区  · 5 月前

    我想做一个ASP。NET web窗体,它将文本从TextBox发送到Visual Studio中的SQL数据库。我找到了两个教程,完全符合我的要求,但它们在教程进行到一半时都有相同的错误。在TextBox中的每个TextBox下。文本,有一个错误,上面写着:

    "CS0103: The name 'TextBox' does not exist in the current context".
    

    以下是2个教程的链接:

    这是我当前的代码(in WebForm.aspx.cs ,不是完整的代码):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Net;
    using System.Net.Mail;
    using System.Drawing;
    using System.Configuration;
    using System.Data.SqlClient;
    using System.Data;
    using System.Text;
    using System.IO;
    public partial class _Default : System.Web.UI.Page 
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
        protected void Page_Load(object sender, EventArgs e) 
        {
            con.Open();
        }
        protected void Register_Click(object sender, EventArgs e)
        {
            SqlCommand cmd = new SqlCommand("insert into storedatabase values('"+TextBox2.Text+"')")
    
        }
    }
    

    这是TextBox2(in WebForm.aspx ):

    <asp:TextBox ID="TextBox2" runat="server" MaxLength="20"></asp:TextBox>
    

    我正在使用Visual Studio 2022。净值4.7.2。

    我在谷歌上几乎搜索过所有地方,以下是我尝试过的主要内容:

    • 使用潜在修复将TextBox2转换为变量
    • 检查TextBox2是否具有“runat=”server“”
    • 检查拼写

    其他所有搜索结果要么和我没有同样的问题,要么和我有完全相同的问题,但答案被付费墙屏蔽了,要么没有答案,要么有和我一样的问题,但是答案没有说明在哪里以及如何解决,或者是一篇有人与论坛版主发生争执的帖子。我搜索了太多,每次搜索与我的问题相关的任何内容时,谷歌第1-2页中的所有链接都变成了紫色。

    任何帮助都将不胜感激。非常感谢。

    1 回复  |  直到 5 月前
        1
  •  0
  •   Albert D. Kallal    5 月前

    首先,我们实际上需要看到更多的页面标记。

    接下来,不,这里的人不会看你在YouTube上发布的某个链接上的视频。

    好的,请记住,在.net框架这样的优秀系统出现之前,打开与数据库的连接,然后将该连接全局限定在应用程序的范围内,并保持连接打开,这通常是标准的公平做法。

    然而,有了新的工具,就会为你创建一个“连接池”,作为一名开发人员,你的工作就是打开这样的连接,但你要让系统为你处理和关闭连接!

    然后,如果以后你想做更多的数据库操作,那么系统会检查连接的“池”,并为你重复使用+重新循环这些连接。因此,这消除了开发人员必须“尝试”并保持打开或维护此类连接的情况。

    因此,在页面加载事件中尝试打开连接是没有意义的。请记住,每次发布任何回复(如点击按钮)时,页面加载事件都会触发,然后你的按钮代码存根就会运行。

    接下来,您确实希望使用SQL参数,因为使用web平台,您将面临SQL注入的高风险。然而,同样糟糕的是试图“记住”字符串的SQL规则(用引号括住文本)。对于数字(不需要引号)和日期,再次需要引号。因此,通过采用SQL参数,而不是使用字符串连接,您会发现您编写的代码量大致相同,但SQL语法错误会出现巨大的下降。换句话说,采用参数会降低技能、脑力和SQL代码出错的可能性。通常,最多你会多出1行代码,但最终得到的代码更容易阅读,更容易维护,当然也更可靠,而且你的代码是SQL注入安全的。

    此外,您没有提到这是一个带有子网页的主网页,还是一个没有主网页的简单网页表单。还要记住,放置在数据感知控件(如GridView、Repeater、ListView等)内的文本框(或任何控件)不允许直接引用页面上的控件(如文本框),因为可能有一行数据或20行数据,因此当你引用文本框时,你指的是哪一行数据?

    因此,使用简单标记的最简单示例是您所拥有的文本框(但是,正如我所说,省略其他细节,如使用Repeater或GridView等,意味着以下示例不起作用。

    因此,假设您的页面上有一个简单的文本框,那么整个页面的标记如下:

    <%@ Page Language="C#" 
        AutoEventWireup="true" 
        CodeBehind="SimpleInsert1.aspx.cs" 
        Inherits="CSharpWebApp.Test7.SimpleInsert1" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
    
    
                <asp:TextBox ID="TextBox2" runat="server" MaxLength="20">
                </asp:TextBox>
                <br />
                <asp:Button ID="Button1" runat="server" Text="Insert Data"
                    OnClick="Button1_Click"
                    />
    
                <br />
                <br />
                <br />
                <asp:Label ID="Label1" runat="server" Text="">
                </asp:Label>
    
    
            </div>
        </form>
    </body>
    </html>
    

    当然,当您创建空白的新web表单页面时,上述所有标记都将为您创建,我们添加的标记将是我们在开始和结束表单标记内添加的文本。

    因此,后面的代码现在变成了这样:

        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            string strSQL =
                "insert into storedatabase (MyColumnName) values(@MyValue)";
    
            using (SqlConnection con = 
                new SqlConnection(ConfigurationManager.ConnectionStrings["TEST4"].ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(strSQL, con))
                {
                    con.Open();
                    cmd.Parameters.Add("@MyValue", SqlDbType.NVarChar).Value = TextBox2.Text;
                    cmd.ExecuteNonQuery();
                }
            }
        }
    

    请注意,在你的SQL中,你真的(但真的是为了避免未来几年的世界贫困和痛苦)想指定要用于插入值的列。

    SQL参数的命名通常与列名相同,但前缀为“@”。

    因此,假设数据库中此列值的列名为“FirstName”,则建议的代码为:

            string strSQL =
                "insert into storedatabase (FirstName) values(@FirstName)";
    
            using (SqlConnection con = 
                new SqlConnection(ConfigurationManager.ConnectionStrings["TEST4"].ConnectionString))
            {
                using (SqlCommand cmd = new SqlCommand(strSQL, con))
                {
                    con.Open();
                    cmd.Parameters.Add("@FirstName", SqlDbType.NVarChar).Value = TextBox2.Text;
                    cmd.ExecuteNonQuery();
                }
            }
    

    因此,虽然我们最终编写了那一行额外的代码(cmd.Parameters.Add),但我们不必使用带有“'”和各种杂乱垃圾的杂乱字符串连接。这样的垃圾会在你的代码中产生非常不稳定和难以阅读的字符串。

    当然,这消除了SQL注入问题。因此,使用字符串连接,然后一个“”(引号),一个“,”或其他什么,你所有的代码和努力都会偏离正轨。将这样的代码与SQL混合,然后与一些文本框控件混合,很容易搞砸。不要这样做,否则你会花很多时间试图让简单的代码工作。

    此外,请注意,在上面非常接近,我们没有编写代码来关闭连接。这就是“使用区块”的目的。因此,我们要打开连接,但不需要编写代码来关闭连接(顺便说一句,你的示例代码过去和现在都缺少关闭你打开的连接的代码。你不想打开数据库连接,然后忘记关闭它。但是,由于代码复杂、错误等,这对开发人员来说变得非常困难,因此我们采用了using代码块,从而自动为我们处理关闭和处理打开的连接,但巨大的好处是,现在.net系统将为你回收和管理连接池!!!

    因此,您不必关闭连接,系统会为您完成此操作!更好的奖励积分是,如果存在开放连接,系统将为您重新循环并重新使用它们。换句话说,您现在是否可以100%自由地在代码中始终打开连接,但如果存在现有的“池化”连接,那么它将被重新使用,从头开始打开数据库的性能影响是100%有限的。

    因此,新的设计模式是,您可以(并且应该)在每次需要时打开连接,即使是在一个小的代码存根中,因为如上所述,将使用连接池。如前所述,加分是,如果你的代码有一些错误,那么你就不会出现杂散的未关闭连接,这可能会给网站甚至桌面应用程序带来巨大的混乱,在这些应用程序中,你创建的连接不会被管理或处理。您开始消耗内存,并开始看到打开的数据库连接过多等错误。但是,通过上述使用块,开发人员不再需要尝试管理这个问题。

    最后但同样重要的是,当您编写SQL插入语句时,请将列名括在()后面,然后在语句后面加上values()。

    对于添加参数,不要使用SQL命令对象的.addwith,而是使用add,并按照上述示例使用sqldbType使用强类型参数。