字符串用于在表中存储日期,因未知原因转换为整数

3

我试图把日期作为字符串存储在一个表中,但是这个日期一直转换成一个负的4位数,这个数与日期有关,但是我无法找出我到底哪里出错了。请注意,我正在使用C#和SQL Server的组合。

foreach(DataRow dr in dt.Rows)
{
    int qty = 0;
    string pname = "";

    SqlCommand cmd3 = con.CreateCommand();
    cmd3.CommandType = CommandType.Text;
    cmd3.CommandText = "insert into order_item values('" + orderid.ToString() + "','" + dr["product"].ToString() + "'," +
        "'" + dr["price"].ToString() + "','" + dr["qty"].ToString() + "','"+ dr["total"].ToString() + "')";
    cmd3.ExecuteNonQuery();

    qty = Convert.ToInt32(dr["qty"].ToString());
    pname = dr["product"].ToString();

    SqlCommand cmd6 = con.CreateCommand();
    cmd6.CommandType = CommandType.Text;
    cmd6.CommandText = "update stock set product_qty = product_qty - " + qty + " where product_name = '"+pname.ToString()+"'";
    cmd6.ExecuteNonQuery();

    // date keeps getting updated to negative 4 digit number which coordinates with the date. ex: 14-01-2020 is converting to -2007.
    SqlCommand cmd7 = con.CreateCommand();
    cmd7.CommandType = CommandType.Text;
    **cmd7.CommandText = "update stock_over_time set product_qty = product_qty - " + qty + ", date_changed = " + date.ToString("dd-MM-yyyy") + "" +
        " where product_name = '" + pname.ToString() + "'";**
    cmd7.ExecuteNonQuery();
}

enter image description here


2
原因已知 - 字符串拼接。它会使代码暴露于 SQL 注入和转换错误的风险之中。请使用适当的参数化查询来代替。 - Panagiotis Kanavos
2
将值连接成字符串以生成 SQL 是第一个主要问题;这样做没有任何好处 - (搜索:“SQL 注入”) - Marc Gravell
SQL Server拥有不止一种DataTime类型。检查服务器上的类型。可能是日期存储不正确,因此使用SQL Server Management Studio查询数据库以验证日期是否正确。 - jdweng
@Cid 没有这样的设置。SQL查询中的所有内容都是一个批处理。 - Panagiotis Kanavos
@Cid 我是在回应参数的存在,尽管我怀疑它的存在是出于历史原因,而不是作为注入预防功能。 - Panagiotis Kanavos
显示剩余7条评论
2个回答

5

目前的问题是:

立即

    , date_changed = " + date.ToString("dd-MM-yyyy") + "

将变为

    , date_changed = 15-01-2020

这个值是:-2006,由于日期存储的方式,它对应的时间大约是1894年7月。

一个错误的解决方法是加上引号,但这是错误的 - 这会导致国际化问题(例如,08-01是八月的第一天还是一月的第八天?),SQL注入等一系列问题。

正确的解决方法是在整个过程中使用参数。例如:

cmd7.CommandText = @"
    update stock_over_time
    set    product_qty = product_qty - @qty,
           date_changed = @date
    where  product_name = @pname";

然而,这需要你添加具有相应值的参数。

最简单的方法是使用Dapper:

string pname = ...
int qty = ...
DateTime date = ...
con.Execute(@"
    update stock_over_time
    set    product_qty = product_qty - @qty,
           date_changed = @date
    where  product_name = @pname",
    new { pname, qty, date });

注意:您的所有数据库访问都应该进行参数化,可以像上面那样,或者使用原始的ADO.NET,或者使用EF等工具。不只是这一个地方,而是每个地方

2

不应将日期存储为字符串数据类型,而应将date-changed更改为datetime类型(或仅日期类型,因为存储的值没有“时间”元素)。

此外,建议使用参数化查询以避免SQL注入。

string sql = @"update stock_over_time set product_qty = product_qty - @qty, date_changed = @date where product_name = @pname";

using (SqlConnection connection = new SqlConnection(connString)
{
  connection.Open();
  using (SqlCommand cmd= new SqlCommand(sql, connection))
  {
     cmd.Parameters.Add("@qty", SqlDbType.SqlInt32).value = qty;  
     cmd.Parameters.Add("@date", SqlDbType.SqlDateTime).value =  date;
     cmd.Parameters.Add("@pname", SqlDbType.Varchar, 50).value = pname;
     cmd.ExecuteNonQuery();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接