Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这个简单的更新查询有什么问题?_C#_Asp.net_Sql_Sql Server - Fatal编程技术网

C# 这个简单的更新查询有什么问题?

C# 这个简单的更新查询有什么问题?,c#,asp.net,sql,sql-server,C#,Asp.net,Sql,Sql Server,除了不安全之外。。。我没有收到错误消息,但该行未更新。查询后的rows整数设置为1,表示有1行受到影响 String query = "UPDATE contacts SET contact_name = '" + ContactName.Text.Trim() + "', " + "contact_phone = '" + Phone.Text.Trim() + "', " + "contact_fax = '" + Fax.Text.Trim(

除了不安全之外。。。我没有收到错误消息,但该行未更新。查询后的rows整数设置为1,表示有1行受到影响

String query = "UPDATE contacts SET contact_name = '" + ContactName.Text.Trim() + "', " +
            "contact_phone = '" + Phone.Text.Trim() + "', " +
            "contact_fax = '" + Fax.Text.Trim() + "', " +
            "contact_direct = '" + Direct.Text.Trim() + "', " +
            "company_id = '" + Company.SelectedValue + "', " +
            "contact_address1 = '" + Address1.Text.Trim() + "', " +
            "contact_address2 = '" + Address2.Text.Trim() + "', " +
            "contact_city = '" + City.Text.Trim() + "', " +
            "contact_state = '" + State.SelectedValue + "', " +
            "contact_zip = '" + Zip.Text.Trim() + "' " + 
            "WHERE contact_id = '" + contact_id + "'";

String cs = Lib.GetConnectionString(null);
SqlConnection conn = new SqlConnection(cs);

SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
cmd.Connection.Open();
int rows = cmd.ExecuteNonQuery();

首先,它极易受到注射攻击

在更日常的层面上,任何包含单个撇号字符的输入都会破坏语法。您的数据中是否有撇号

编辑-第二个想法 当您刚刚学习时,请注意必须调用
conn.Close()
关闭与数据库的连接,否则连接将在数据库服务器上保持打开状态,直到垃圾收集开始处理
conn
实例。或者,请参见
使用(){}
构造

在这里稍微抓住救命稻草,但尝试显式事务

SqlTransaction trans;
conn.Open(); 
try 
{
    trans = conn.BeginTransaction();
    int rows = cmd.ExecuteNonQuery(); 
    trans.Commit();
}
catch 
{
     trans.Rollback();
}
conn.Close();

出于以下几个原因,您应该使用参数化查询:

  • 消除嵌入式apos破坏查询的可能性
  • 保护数据库/网站不受sql注入的影响
此外,如果cmd返回1,则该行已更新。您可能需要检查您的期望

String query = @"
    UPDATE contacts 
    SET contact_name = @contact_name, contact_phone = @contact_phone, contact_fax = @contact_fax, 
        contact_direct = @contact_direct , company_id = @company_id, contact_address1 = @contact_address1, 
        contact_address2 =@contact_address2, contact_city = @contact_city , contact_state = @contact_state,  
        contact_zip = @contact_zip 
    WHERE contact_id = @contact_id";

String cs = Lib.GetConnectionString(null);
using (SqlConnection conn = new SqlConnection(cs))
{
    using (SqlCommand cmd = conn.CreateCommand())
    {
        cmd.Parameters.AddWithValue("@contact_name", ContactName.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_phone", Phone.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_fax", Fax.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_direct", Direct.Text.Trim());
        cmd.Parameters.AddWithValue("@company_id", Company.SelectedValue);
        cmd.Parameters.AddWithValue("@contact_address1", Address1.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_address2", Address2.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_city", City.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_state", State.SelectedValue);
        cmd.Parameters.AddWithValue("@contact_zip", Zip.Text.Trim());
        cmd.Parameters.AddWithValue("@contact_id", contact_id);
        cmd.CommandText = query;
        cmd.Connection.Open();
        int rows = cmd.ExecuteNonQuery();
    }
}
现在,看起来不是更干净了吗?当你明白为什么,它会给你一种温暖的模糊感觉,让你晚上睡得很好

澄清

你提出的问题是“这个问题出了什么问题”。答案是什么都没有。这个查询没有问题

问题在于您的页面代码,即使有5个人认为查询没有问题,您也没有发布页面代码

John更清楚地描述了我所说的“您可能需要检查您的期望…”和“您需要在执行查询之前检查进入参数的数据,以确保它们符合您的要求”,但让我再次简要指出:

所示的查询表面上是正确的,应该按预期执行。您可能遇到的是周围代码的逻辑中的一个缺陷

最有可能的情况是,您在page_load中进行数据绑定,而没有IsPostback保护,从而用原始数据覆盖输入值

您只需要在第一次加载时加载和绑定控件/页面一次。此后,控件的状态将保留在viewstate中,viewstate存储在html中的一个隐藏字段中。如果在每次页面加载时仅绑定到数据源,则会覆盖任何输入

让我们来看看这是如何工作的

这里有一个适当的逻辑流程

protected void Page_Load(object sender, EventArgs e)
{
    System.Diagnostics.Trace.WriteLine("Page_Load");
    if (!IsPostBack)
    {
        System.Diagnostics.Trace.WriteLine("\tBind TextBox1");
        TextBox1.Text = "Initial Value";
    }
    System.Diagnostics.Trace.WriteLine("\tTextBox1.Text = " + TextBox1.Text);
}

protected void Button1_Click(object sender, EventArgs e)
{
    System.Diagnostics.Trace.WriteLine("Button1_Click");
    System.Diagnostics.Trace.WriteLine("\tTextBox1.Text = " + TextBox1.Text);
}
如果加载此页面,请在文本框中输入“新值”,然后单击按钮1,这是跟踪显示的内容:

Page_Load Bind TextBox1 TextBox1.Text = Initial Value Page_Load TextBox1.Text = New Value Button1_Click TextBox1.Text = New Value 你会得到你可能正在经历的结果

Page_Load Bind TextBox1 TextBox1.Text = Initial Value Page_Load Bind TextBox1 TextBox1.Text = Initial Value Button1_Click TextBox1.Text = Initial Value 页面加载 绑定文本框1 TextBox1.Text=初始值 页面加载 绑定文本框1 TextBox1.Text=初始值 按钮1\u单击 TextBox1.Text=初始值
但同样,一种实用的调试技术可以帮助您在执行查询之前打断update方法,并检查这些值,以验证它们是否与您认为的值相同,然后再继续执行。

如果它仍然不起作用,下面是一些调试问题:

  • 此代码位于何处,在页面生命周期的哪个部分调用
  • Lib.GetConnectionString(null)
    返回什么
  • 您是否在更新查询之前设置了断点以确保存在正确的数据
我的最佳猜测是,由于您正在更新现有记录,因此您的回发值很可能在
Page\u Load
上被数据库中的现有数据覆盖,这意味着查询实际上正在更新,但它正在使用数据库中已存在的相同数据进行更新


在填充页面上的任何文本框之前,您要做的是选中
if(!IsPostBack).
。这样,如果存在回发,则文本框中的数据将填充回发值,而不是数据库中的值。

查看此问题中的其他讨论,您的查询似乎有效,但此处出现了一些不相关的错误。有些东西有时会咬我的屁股:

  • 你真的确定你正在运行你认为是的查询吗?在点击
    cmd.ExecuteNonQuery()
    之前,先进入调试器。这些参数是您认为的吗?命令文本仍然是您认为应该是的吗

  • 您是否正在更新正确的数据库?进入调试器并检查连接字符串(
    cs
    )。当您需要开发数据库时,您可能仍然连接到生产数据库,反之亦然

  • 如果在SQL Management Studio中手动运行查询,会发生什么情况?行是否更新为您认为应该更新的内容


如果联系人id是一个整数,请尝试不要将其放在单引号中

更改:

"WHERE contact_id = '" + contact_id + "'";


更新:正如约翰在评论中指出的那样,这两个条款没有显著差异。不带引号的查询可能会更快,因为在这种情况下,您将跳过强制转换/转换。

为了快速排除故障,您可以尝试使用SQL Server探查器。它比你想象的更容易使用。我保证

  • 运行Sql Server探查器(随Sql Server提供)
  • 单击文件->新建跟踪
  • 连接到数据库
  • 接受默认跟踪属性
  • 轰!这是录音
  • 运行你的应用程序。如果您已经在进行更新的页面上,请刷新它,或者点击按钮或导致更新的任何东西
  • 检查跟踪中出现的记录。都是实时的
  • 可选:单击“擦除”按钮,然后重试。您将能够看到探查器中正在执行的确切SQL
  • 当你喝醉的时候
    "WHERE contact_id = '" + contact_id + "'";
    
    "WHERE contact_id = " + contact_id;