如何以毫秒为单位将日期时间插入到 Access 数据库中?

TRX*_*TRX 6 c# ms-access datetime

我正在尝试使用 C# 将日期 + 时间插入到 Access 数据库中。时间字符串中包含毫秒,例如:

"2015-03-23 11:22:33.123"`
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

string strName = "somestring";
string strDate = "2015-03-23 11:22:33.123"

sql = @"insert into table_name  ([name], [date]) values (@Name, @Date)";

using (OleDbCommand command = new OleDbCommand(sql))
{
    command.Connection = openCon;
    command.Parameters.AddWithValue("@Name", strName);
    command.Parameters.AddWithValue("@Date", strDate ); // <-- error here          
    openCon.Open();
    recordsAffected = command.ExecuteNonQuery();
    openCon.Close();
}
Run Code Online (Sandbox Code Playgroud)

我在ExcuteNonQuery(); 如果我删除日期时间字符串,则代码有效。

那么如何将带毫秒的日期时间插入到 Access 数据库中呢?

Gus*_*tav 5

您混淆了日期时间和字符串。始终使用 DateTime 作为日期/时间值或尽早转换为 DateTime。因此:

string strDate = "2015-03-23 11:22:33.123";
DateTime datDate = DateTime.Parse(strDate);
// ...
//    command.Parameters.AddWithValue("@Date", datDate ); // <-- error here 

command.Parameters.Add("@Date",OleDbType.Date);
command.Parameters[0].Value = datDate;                    // <-- no error
Run Code Online (Sandbox Code Playgroud)

请注意,虽然 Access 会正确存储该值,但它或 VBA 不会显示毫秒,而是会进行 4/5 舍入到秒。当然,如果您只从 C# 应用程序中读取这些值,那么这并不重要。

当插入到我的毫秒应用程序中时,该值将被正确插入,如下所示:

DateTimeMs          SortValue       DateFull                CDouble             RoundSecSQL         MsecSQL MsecVBA SecondDec SecondStd
23-03-2015 11:22:33 60438568953123  23-03-2015 11:22:33.123 42086,4739944792    42086,4739930556    123     123     33,123    33
23-03-2015 11:45:31 60438570330707  23-03-2015 11:45:30.707 42086,4899387384    42086,4899305556    707     707     30,707    31
Run Code Online (Sandbox Code Playgroud)


Gor*_*son 5

访问“日期/时间”字段类型的标称分辨率为一秒。也就是说,当日期/时间值在 Access 中显示、使用预定义或自定义格式进行格式化或使用DateAddDatePart等函数进行操作时,我们可以指定的最小时间单位是

将 OLEDB 与 .NET 结合使用

.AddWithValue通过 Access 数据库使用时System.Data.OleDbDateTime日期/时间字段的参数不得具有毫秒值,否则插入/更新将失败。那是,

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
cmd.Parameters.AddWithValue("?", dt);
cmd.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

将会失败

标准表达式中的数据类型不匹配。

然而,正如古斯塔夫在他的回答中指出的那样,我们可以使用.AddwithOleDbType.Date添加一个DateTime包含毫秒的参数,

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
cmd.Parameters.Add("?", OleDbType.Date).Value = dt;
cmd.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

并且该值将完整地存储在“访问日期/时间”字段中。我们可以通过检索存储的值并检查它来验证这一点

cmd.CommandText = "SELECT [date] FROM table_name WHERE ID = 13";
DateTime rtn = Convert.ToDateTime(cmd.ExecuteScalar());
Console.WriteLine(rtn.Millisecond);
Run Code Online (Sandbox Code Playgroud)

...打印“123”,表明毫秒部分是返回值的一部分。

诀窍在于 Access 本身并没有为我们提供有效处理这些日期/时间值的毫秒部分的工具。要从 Access/VBA 中执行此操作,需要一些额外的编码,如此处另一个站点上的一篇文章所述

(当然,如果您只想将值拉回到 .NET 应用程序中,那么您可以只使用上面的代码片段。)

将 ODBC 与 .NET 结合使用

使用相同的方法会System.Data.Odbc产生略有不同的结果。Access ODBC 驱动程序将接受DateTime带有毫秒值的参数.Add.AddWithValue但不会存储毫秒值。

此外,如果我们尝试检索使用 OLEDB 存储的包含毫秒的日期/时间值,则 Access ODBC 驱动程序会删除毫秒。也就是说,如果我们尝试使用以下 ODBC 代码来检索我们通过上面的 OLEDB 示例存储的“毫秒值”...

// cmd is now an OdbcCommand object
cmd.CommandText = "SELECT [date] FROM table_name WHERE ID = 13";
DateTime rtn = Convert.ToDateTime(cmd.ExecuteScalar());
Console.WriteLine(rtn.Millisecond);
Run Code Online (Sandbox Code Playgroud)

...它打印“0”,即使我们可以通过执行以下操作来验证 Double 值的毫秒部分是否已存储在数据库中

cmd.CommandText = "SELECT CDbl([date]) AS foo FROM table_name WHERE ID = 13";
Double rtn = Convert.ToDouble(cmd.ExecuteScalar());
Console.WriteLine(rtn);
Run Code Online (Sandbox Code Playgroud)

并检查 Double 值的小数部分。

备择方案

如果您想保持日期/时间字段类型的标称 1 秒分辨率,您可以...

将值四舍五入到最接近的秒:

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
if (dt.Millisecond >= 500)
{
    dt = dt.AddSeconds(1);
}
dt = dt.AddMilliseconds(-dt.Millisecond);
cmd.Parameters.AddWithValue("?", dt);
cmd.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

或者,如果您想保留毫秒,那么您必须将截断(未舍入)的日期/时间和毫秒存储在单独的字段中,或者可能只将原始字符串值存储在文本字段中。