C#潜在的日期格式问题-System.Data.SqlClient.SqlException:'在'x'附近的语法不正确。

时间:2018-07-18 09:24:46

标签: c# sql

该应用程序的目的是从Sql数据库中选择数据到Windows窗体数据网格。我为日期时间选择器实现了自定义格式,但仍收到此错误。这是应用程序的属性和以下代码

Date Time Picker Properties

        private void startTimePicker1_MouseDown(object sender, MouseEventArgs e)
    {
        startTimePicker1.CustomFormat = "yyyy-MM-dd hh:mm:ss";
        startTimePicker1.Format = DateTimePickerFormat.Custom;
    }

    private void endTimePicker1_MouseDown(object sender, MouseEventArgs e)
    {
        endTimePicker1.CustomFormat = "yyyy-MM-dd hh:mm:ss";
        endTimePicker1.Format = DateTimePickerFormat.Custom;
    }

    private void loadBtn_Click(object sender, EventArgs e)
    {
        startTimePicker1.CustomFormat = "yyyy-MM-dd hh:mm:ss";
        startTimePicker1.Format = DateTimePickerFormat.Custom;

        endTimePicker1.CustomFormat = "yyyy-MM-dd hh:mm:ss";
        endTimePicker1.Format = DateTimePickerFormat.Custom;

        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["DBName"].ConnectionString))
        {
            if(db.State==ConnectionState.Closed)
            {
                db.Open();
                string query = "select z.ItemName, x.Quantity, x.CreateDate" +
                                 " from Invoice_Itemized x inner join Inventory z on x.ItemNum = z.ItemNum inner join Departments d on z.Dept_ID = d.Dept_ID" +
                                $"where x.CreateDate BETWEEN '{ startTimePicker1 }' and '{ endTimePicker1 }' and d.SubType = 'TYPE'";

                liquorBindingSource.DataSource = db.Query<Liquor>(query, commandType: CommandType.Text);
            }
        }

在运行时查询输出以下值

select z.ItemName, x.Quantity, x.CreateDate from Invoice_Itemized x inner join Inventory z on x.ItemNum = z.ItemNum inner join Departments d on z.Dept_ID = d.Dept_IDwhere x.CreateDate BETWEEN 'System.Windows.Forms.DateTimePicker, Value: 7/18/2018 2:44:00 AM' and 'System.Windows.Forms.DateTimePicker, Value: 7/18/2018 4:19:01 AM' and d.SubType = 'TYPE'

此查询已在SSMS中成功执行,在调试了数小时后,我陷入了困境。

2 个答案:

答案 0 :(得分:1)

您在这里有两个不同的问题。

一种是您将DateTimePicker的引用传递到字符串插入中,导致该字符串包含从DateTimePicker.ToString()返回的值,而不是所需的值。

第二个问题是,您首先不应该将日期作为字符串传递给数据库。相反,您应该使用SQL参数来传递DateTime的实例。我不确定您使用的是什么ORM,因此无法为您提供代码示例。

此外,正如fubo在对该问题的评论中所写,Where关键字前缺少空格。

答案 1 :(得分:1)

string query = "select z.ItemName, x.Quantity, x.CreateDate" +
      " from Invoice_Itemized x inner join Inventory z on x.ItemNum = z.ItemNum inner join Departments d on z.Dept_ID = d.Dept_ID" +
      $"where x.CreateDate BETWEEN '{ startTimePicker1 }' and '{ endTimePicker1 }' and d.SubType = 'TYPE'";

liquorBindingSource.DataSource = db.Query<Liquor>(query, commandType: CommandType.Text);

这是非常有害的,并且可能导致多种问题,包括格式/文化问题(它在某些计算机上工作,但在其他计算机上工作,具体取决于语言环境)-和(更重要的是)SQL注射风险。它还不允许重复使用查询计划缓存。

由于看起来您在这里使用的是“ dapper”,因此dapper经过了设计设计,可轻松进行参数设置:

liquorBindingSource.DataSource = db.Query<Liquor>(@"
        select z.ItemName, x.Quantity, x.CreateDate
        from Invoice_Itemized x
        inner join Inventory z on x.ItemNum = z.ItemNum
        inner join Departments d on z.Dept_ID = d.Dept_ID
        where x.CreateDate BETWEEN @start and @end and d.SubType = 'TYPE'",
    new { start = startTimePicker1.Value, end = endTimePicker1.Value });

这会将值作为类型参数传递(假设.Value在这里是DateTime),避免了所有本地问题 并消除了SQL注入的风险。如果.Value不是 DateTime,而只是string,那么我会使用:

new { start = DateTime.Parse(startTimePicker1.Value),
        end = DateTime.Parse(endTimePicker1.Value) }

作为第二个参数。