【问题标题】:Error when saving datetime to a SQL Server database将日期时间保存到 SQL Server 数据库时出错
【发布时间】:2015-04-20 20:29:07
【问题描述】:

我在业余时间做一些 C# Winforms 编码,只是为了掌握所有内容。我有一个 SQL 脚本,它在 vs2012 上创建一个本地数据库,如下所示:

-- Creating table 'Users'--
CREATE TABLE [dbo].[Users]
(
    [UserID] int IDENTITY(1,1) NOT NULL,
    [Surname] nvarchar(30)  NOT NULL,
    [Forename] nvarchar(30)  NOT NULL,
    [Company] nvarchar (30) NOT NULL,
    [SecurityLevel] int NOT NULL,
    [IssueDate] DateTime  NOT NULL,
    [ExpiryDate] DateTime  NOT NULL,
    [CardID] int NOT NULL,
);
GO

现在我想将详细信息保存到该表中,所以我创建了一个方法:

  private void btnSaveDetails_Click(object sender, EventArgs e)
  {
        SqlConnection sc = new SqlConnection();
        SqlCommand com = new SqlCommand();
        sc.ConnectionString = (Properties.Settings.Default.BioEngineering);
        sc.Open();
        com.Connection = sc;
        com.CommandText = ("INSERT INTO Users (Forename, Surname, Company, SecurityLevel, IssueDate, ExpiryDate, CardID) VALUES ('" + this.txtFirstName.Text + "','" + this.txtLastName.Text + "','" + this.txtCompany.Text + "','" + this.cboSecurityLevel.Text + "','" + this.dtpIssueDate.Value + "','" + this.dtpExpiryDate.Value + "','" + this.cboCardID.Text + "');");

        com.ExecuteNonQuery();
        sc.Close();
    }

当我运行代码时出现错误

将 varchar 数据类型转换为 datetime 数据类型导致值超出范围

我知道它与 SQL 或 C# 等效的日期时间格式有关,但我不知道如何格式化日期时间以符合错误。有任何想法吗?我尝试使用命令文本行对其进行格式化,但似乎没有解决问题。

【问题讨论】:

  • 您应该使用参数化查询。不仅如此,您的问题的一部分是 .Value,SQL 期望 DateTime 的格式为:“yyyy-MM-dd HH:mm:ss.fffffff”,具体取决于列类型。此外,DateTime2 更适合 SQL 列类型。
  • 不应该,必须。您的问题看起来不像是代码问题,而更像是数据问题。你的价值观是什么?
  • 日期时间值来自日期选择器框
  • @EBrown 您对参数化查询的看法是正确的,但您本可以停在那里。一旦 OP 转向正确的参数使用,字符串强制和预期格式就无关紧要了。
  • goldeneye 请阅读此内容:msdn.microsoft.com/en-us/library/zdtaw1bw(v=vs.110).aspx 您对 DateTimePicker.Value 的使用将其转换为默认的、本地化的、SQL 不可表示的字符串。正如@DonBoitnott 和我所说,切换到参数化查询不仅可以解决这个问题,而且可以消除任何人都可以在你的代码上执行的大量 SQL 注入攻击。另外:msdn.microsoft.com/en-us/library/vstudio/…

标签: c# sql sql-server winforms


【解决方案1】:

Datepicker.Value 返回为

[Your_System_Short_Date_Format] + [Space] + [Your_System_Long_Time_Format]

我不知道为什么使用这种格式,但只是在添加 DateTimePicker 时使用默认长格式检查时发现。

因此,您传递的值取决于您的系统 [Regional/Calendar] 设置,其中 SQL 引擎期望采用 EBrown 所说的格式

yyyy-MM-dd HH:mm:ss.fffffff

所以如果你确实想连接,那么你可以使用 like

 command.CommandText = 
    "INSERT INTO EMPLOYEES(DateOfBirth) VALUES ('" +
     dtpDateOfBirth.Value.ToString("yyyy-MM-dd HH:mm:ss") + "')";

但我真的建议您从一开始就保持使用参数的习惯。否则,在制作了一个庞大的应用程序之后,您可能需要返回将这些串联更改为参数。

很简单

command.CommandText = "INSERT INTO EMPLOYEES(DateOfBirth) VALUES (@dob)";

command.Parameters.Add("@dob", SqlDbType.DateTime).Value = dtpDateOfBirth.Value;

     // Or Simply

command.Parameters.AddWithValue("@dob", dtpDateOfBirth.Value);

您可以使用参数添加更多具有不同数据类型的参数。 SqlCommand 类安全地将它们转换为 SqlCommand,尤其是从注入攻击中。

【讨论】:

    【解决方案2】:

    首先,你这样做的方式是非常粗暴的运行sql语句的方式,容易出现大量错误、内存泄漏、sql注入攻击和安全问题。

    --你应该使用using 语句来处理连接和命令对象,更好的错误处理。

    -- 你应该使用参数化查询或存储过程或 ORM,如 nhibernate 或 EF。

    无论如何,您的代码中的错误如下

    将日期字段转换为此格式.ToString("MM/dd/YYYY")

     private void btnSaveDetails_Click(object sender, EventArgs e)
        {
            SqlConnection sc = new SqlConnection();
            SqlCommand com = new SqlCommand();
            sc.ConnectionString = (Properties.Settings.Default.BioEngineering);
            sc.Open();
            com.Connection = sc;
            com.CommandText = ("INSERT INTO Users (Forename, Surname, Company, SecurityLevel, IssueDate, ExpiryDate, CardID) VALUES ('" + this.txtFirstName.Text + "','" + this.txtLastName.Text + "','" + this.txtCompany.Text + "','" + this.cboSecurityLevel.Text + "','" + this.dtpIssueDate.Value.ToString("MM/dd/YYYY") + "','" + this.dtpExpiryDate.Value.ToString("MM/dd/YYYY") + "','" + this.cboCardID.Text + "');");
    
            com.ExecuteNonQuery();
            sc.Close();
        }
    

    【讨论】:

    • 我知道人,ORM,存储过程,参数化查询,很多选项......对他来说一步一步,让他先感受一下:)。你们太认真了,想在101课上教他最好的做法。
    • 哇,你认为学习编码就像生病去看医生
    • 我可以找到问题人中每一行代码的问题,我们并没有纠正每一行。
    • 并在命令/连接对象周围使用语句,为所有数据库调用编写单独的服务,并且可以通过依赖注入将其注入表单等。
    • 发现代码中的其他缺陷很常见。完整的答案也以简洁明了的方式充实了这些问题。
    猜你喜欢
    • 1970-01-01
    • 2017-03-25
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多