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 数据库中呢?
您混淆了日期时间和字符串。始终使用 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)
访问“日期/时间”字段类型的标称分辨率为一秒。也就是说,当日期/时间值在 Access 中显示、使用预定义或自定义格式进行格式化或使用DateAdd或DatePart等函数进行操作时,我们可以指定的最小时间单位是秒。
将 OLEDB 与 .NET 结合使用
当.AddWithValue通过 Access 数据库使用时System.Data.OleDb,DateTime日期/时间字段的参数不得具有毫秒值,否则插入/更新将失败。那是,
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)
或者,如果您想保留毫秒,那么您必须将截断(未舍入)的日期/时间和毫秒存储在单独的字段中,或者可能只将原始字符串值存储在文本字段中。
| 归档时间: |
|
| 查看次数: |
6462 次 |
| 最近记录: |