从字符串转换datetime时转换失败

时间:2009-12-26 10:21:49

标签: c# sql sql-server

当我编译下面的代码时,“从字符串转换datetime时转换失败”异常引发,那有什么问题?

代码:

DateTime after3Dyas = DateTime.Now.AddDays(3);

        try
        {
            Con.Open();
            SqlCommand Command = Con.CreateCommand();
            Command.CommandText = "Select * from Forcast Where City='" + city + "' And Date between '" + DateTime.Now.Date + "' and '" + after3Dyas.Date + "'";

            SqlDataReader thisReader = Command.ExecuteReader();

            int i=0;
            while (thisReader.Read())
            {
                //do something
                i++;

            }

            thisReader.Close();

4 个答案:

答案 0 :(得分:4)

数据库正在尝试转换DateTime.ToString给你的任何值...你真的想要相信你的调用机器上的.NET和SQL Server使用完全相同的格式吗?这听起来很脆弱。

通过不首先直接将值放入SQL中来避免这种情况 - 使用parameterized query。这不仅避免了转换问题,而且(同样重要的是)避免了SQL injection attacks

示例代码:

DateTime start = DateTime.Now;
DateTime end = start.AddDays(3);
string sql = @"
SELECT * FROM Forecast
WHERE City = @City AND Date BETWEEN @StartDate AND @EndDate";

// Don't forget to close this somewhere. Why not create a new connection
// and dispose it?
Con.Open();
using (SqlCommand command = new SqlCommand(sql, Con))
{
    command.Parameters.Add("@City", SqlDbType.NVarChar).Value = city;
    command.Parameters.Add("@StartDate", SqlDbType.DateTime).Value = start;
    command.Parameters.Add("@EndDate", SqlDbType.DateTime).Value = end;
    using (SqlDataReader reader = command.ExecuteReader())
    {
        int i = 0;
        while (reader.Read())
        {
            //do something
            i++;
        }
    }
}

答案 1 :(得分:0)

请尝试以下格式:

DateTime.Now.ToString("yyyy-MM-dd") 

但由于安全问题,我强烈建议您使用参数:

Command.CommandText = 
     "Select * from Forcast Where City=@City And Date between @StartDate and @EndDate";

SqlParameter city = new SqlParameter("@City", SqlDbType.VarChar, 10);
city.Value = yourCityValue;
Command.Parameters.Add(city);

SqlParameter startDate = new SqlParameter("@StartDate", SqlDbType.DateTime);
startDate.Value = yourStartDate;
Command.Parameters.Add(startDate);

SqlParameter endDate = new SqlParameter("@EndDate", SqlDbType.DateTime);
endDate.Value = yourEndDate;
Command.Parameters.Add(endDate);

答案 2 :(得分:0)

  1. 您应该使用参数化查询。
  2. 如果您不想使用参数化查询,请使用CONVERT函数:

    "Select * from Forcast Where City='" + city + "' And Date = CONVERT(DATETIME,'" + DateTime.Now.ToString("yyyy-MM-dd") + "',120)

  3. CONVERT(Datetime,'2009-12-25',120)将varchar类型转换为具有指定格式的datetime类型。它也有助于sql注入,但参数是更好的解决方案。

答案 3 :(得分:0)

您应该尽可能使用参数化查询。有几个原因,如:

  1. 您将避免sql注入攻击。
  2. 参数化查询的执行计划将由sql server缓存,因此在使用不同参数值执行相同查询时,您将获得更好的性能。
  3. 您将避免需要转义字符串参数。
  4. 有关详细信息,请参阅以下文章:http://www.codeproject.com/KB/database/SqlInjectionAttacks.aspx