Ich benutze Dapper, um Objekte in / aus SQLite einzufügen und abzurufen: Ein Objekt hat eine Eigenschaft vom Typ DateTime (und DateTimeOffset), die ich persistieren und mit Millisekunden Genauigkeit abrufen muss. Ich kann keine Möglichkeit finden, den Wert korrekt abzurufen, weil Dapper fehlschlägt mit:
System.FormatException : String was not recognized as a valid DateTime.
in System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)
in System.DateTime.ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style)
in System.Data.SQLite.SQLiteConvert.ToDateTime(String dateText, SQLiteDateFormats format, DateTimeKind kind, String formatString)
in System.Data.SQLite.SQLite3.GetDateTime(SQLiteStatement stmt, Int32 index)
in System.Data.SQLite.SQLite3.GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, Int32 index, SQLiteType typ)
in System.Data.SQLite.SQLiteDataReader.GetValue(Int32Â i)
in System.Data.SQLite.SQLiteDataReader.GetValues(Object[]Â values)
in Dapper.SqlMapper.<>c__DisplayClass5d.<GetDapperRowDeserializer>b__5c(IDataReader r) in SqlMapper.cs: line 2587
in Dapper.SqlMapper.<QueryImpl>d__11`1.MoveNext() in SqlMapper.cs: line 1572
in System.Collections.Generic.List`1..ctor(IEnumerable`1Â collection)
in System.Linq.Enumerable.ToList(IEnumerable`1Â source)
in Dapper.SqlMapper.Query(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in SqlMapper.cs: line 1443
in Dapper.SqlMapper.Query(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in SqlMapper.cs: line 1382
Was muss ich versuchen? Spalte ist vom Typ DATETIME.
Muss ich einen benutzerdefinierten TypeHandler erstellen und DateTime in und aus einer SQLite-Zeichenfolge im Format "o" konvertieren?
Dapper Version 1.38
Ich weiß, dass es alt ist, aber ich habe die Lösung gefunden. Nachdem ich Dapper-Code ausgegraben und analysiert hatte, kam ich auf Folgendes (beachten Sie, dass dies 2019 Jahre ist):
Zuerst müssen Sie einen Datums- / Uhrzeit-Handler erstellen:
public class DateTimeHandler : SqlMapper.TypeHandler<DateTimeOffset>
{
private readonly TimeZoneInfo databaseTimeZone = TimeZoneInfo.Local;
public static readonly DateTimeHandler Default = new DateTimeHandler();
public DateTimeHandler()
{
}
public override DateTimeOffset Parse(object value)
{
DateTime storedDateTime;
if (value == null)
storedDateTime = DateTime.MinValue;
else
storedDateTime = (DateTime)value;
if (storedDateTime.ToUniversalTime() <= DateTimeOffset.MinValue.UtcDateTime)
return DateTimeOffset.MinValue;
else
return new DateTimeOffset(storedDateTime, databaseTimeZone.BaseUtcOffset);
}
public override void SetValue(IDbDataParameter parameter, DateTimeOffset value)
{
DateTime paramVal = value.ToOffset(this.databaseTimeZone.BaseUtcOffset).DateTime;
parameter.Value = paramVal;
}
}
Beachten Sie nun, dass Dapper den Typ DateTimeOffset von .Net in dbType - DateTimeOffset übersetzt. Sie müssen diese Zuordnung entfernen und Ihre eigene wie folgt hinzufügen:
SqlMapper.RemoveTypeMap(typeof(DateTimeOffset));
SqlMapper.AddTypeHandler(DateTimeHandler.Default);
Das ist alles. Jedes Mal, wenn Dapper die DateTimeOffset-Eigenschaft in Ihrem Modell sieht, wird Ihr DateTimeHandler ausgeführt, um dies zu verwalten.