C# 这个简单的更新查询有什么问题?
除了不安全之外。。。我没有收到错误消息,但该行未更新。查询后的rows整数设置为1,表示有1行受到影响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(
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注入的影响
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中手动运行查询,会发生什么情况?行是否更新为您认为应该更新的内容
"WHERE contact_id = '" + contact_id + "'";
到
更新:正如约翰在评论中指出的那样,这两个条款没有显著差异。不带引号的查询可能会更快,因为在这种情况下,您将跳过强制转换/转换。为了快速排除故障,您可以尝试使用SQL Server探查器。它比你想象的更容易使用。我保证
"WHERE contact_id = '" + contact_id + "'";
"WHERE contact_id = " + contact_id;