【问题标题】:SQLite DateTime handling in SQLProviderSQLProvider 中的 SQLite DateTime 处理
【发布时间】:2016-09-04 09:57:32
【问题描述】:

如何通过SQLProvider type-provider 在 SQLite 中使用 DateTime?

SQLite 并没有真正的日期和时间数据类型(请参阅Data types)并将日期存储为文本。我可以传递一个日期字符串并查询它,然后取回一个字符串。所以这是可行的,其中 table3 中的 Date1 存储为字符串:

query {                                         
    for r in table3 do
        select (r.Date1)                                
        } |> Seq.toList

val it : string list =
  ["2016/06/09 0:00:00"; "2016/06/05 0:00:00"; "2016/06/04 0:00:00";
   "2016/06/12 0:00:00"; "2016/06/10 0:00:00"; "2016/06/06 0:00:00";

也可以将 Date1 存储为 DateTime,并在另一个表中存储它。即使 SQLite 不理解 DateTime,我也可以创建一个具有 DateTime 数据类型的列,并且可以在其中存储一个 DateTime 值。例如,我可以在 C#(或 LinqPad)中提取此值。但是当我尝试通过类型提供程序(让我存储 DateTime 值的同一类型提供程序)访问它时,它会出现以下错误:

System.FormatException: String was not recognized as a valid DateTime.

>    at System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)
   at System.Data.SQLite.SQLiteConvert.ToDateTime(String dateText, SQLiteDateFormats format, DateTimeKind kind, String formatString)
   at System.Data.SQLite.SQLite3.GetDateTime(SQLiteStatement stmt, Int32 index)
   at System.Data.SQLite.SQLite3.GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, Int32 index, SQLiteType typ)
   at System.Data.SQLite.SQLiteDataReader.GetValue(Int32 i)
   at <StartupCode$FSharp-Data-SqlProvider>.$SqlRuntime.DataContext.FSharp-Data-Sql-Common-ISqlDataContext-ReadEntities@153.GenerateNext(IEnumerable`1& next)
   at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1.MoveNextImpl()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable`1 source)
   at FSharp.Data.Sql.Runtime.QueryImplementation.executeQuery(ISqlDataContext dc, ISqlProvider provider, SqlExp sqlExp, List`1 ti)
   at FSharp.Data.Sql.Runtime.QueryImplementation.SqlQueryable`1.System-Collections-Generic-IEnumerable`1-GetEnumerator()
   at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable`1 source)
   at <StartupCode$FSI_0075>.$FSI_0075.main@()

table3 中的工作(类型提供程序)查询与 table2 中出现错误的查询之间的区别在于列的数据类型:

LinqPad 正确地将其视为 Table2 中的 DateTime,并且该查询在那里有效:

var dt2 = new System.DateTime(2016,8,30,0,0,0,DateTimeKind.Local);
Table2
    .Where(r => r.Date1 == dt2).Dump();

【问题讨论】:

  • 您使用的是哪个版本的 SQLProvider?
  • @TuomasHietanen 感谢您的回复。我相信我使用的是 1.0.8,但由于我现在没有这个项目,所以我会仔细检查。
  • 听起来很老了。尝试一个新的,因为一些与 SQLite 数据类型相关的问题已在 2 个月前得到解决。 :-)
  • @TuomasHietanen 感谢您的提醒。我确认 DateTime 正在使用 1.0.31。

标签: sqlite datetime f# type-providers


【解决方案1】:

DateTime 类型在 SQLProvider 1.0.31 和 SQLite 1.0.102 的以下版本中按预期工作:

#if INTERACTIVE
#I @"..\packages\SQLProvider.1.0.31\lib"
#r "FSharp.Data.SqlProvider.dll" 
#I @"..\packages\System.Data.SQLite.Core.1.0.102.0\lib\net46"
#r "System.Data.SQLite.dll"
#I @"..\packages\System.Data.SQLite.Linq.1.0.102.0\lib\net46"
#r "System.Data.SQLite.Linq.dll"
#endif

open System
open FSharp.Data.Sql
//open System.Data.SQLite
//open System.Data.SQLite.Linq

[<Literal>]
let connectionString = "Data Source="+ @"C:\tmp\databaseFile.db3"
[<Literal>]
let resolutionPath = __SOURCE_DIRECTORY__ + @"..\..\packages\System.Data.SQLite.Core.1.0.102.0\lib\net46"

type sql = SqlDataProvider<
                Common.DatabaseProviderTypes.SQLITE, 
                connectionString, 
                ResolutionPath = resolutionPath, 
                CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL>

let ctx = sql.GetDataContext() 

let table2 = ctx.Main.Table2   //DateTime
let table3 = ctx.Main.Table3   //Text

【讨论】:

    猜你喜欢
    • 2017-06-16
    • 2017-11-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多