Mappage de TimeSpan dans SQLite et Dapper

c# dapper orm sqlite system.data.sqlite

Question

Je tente d'utiliser Dapper pour interfacer avec un format de base de données existant doté d'une table dont la durée est codée sous forme de ticks dans une colonne BIGINT. Comment puis-je demander à Dapper de mapper la propriété TimeSpan TimeSpan de TimeSpan POCO lors de l'insertion et de la lecture dans la base de données?

J'ai essayé de définir le type de mappage pour TimeSpan sur DbType.Int64 :

SqlMapper.AddTypeMap(typeof(TimeSpan), DbType.Int64);

Et j'ai aussi créé un ITypeHandler , mais la SetValue méthode est jamais appelée:

public class TimeSpanToTicksHandler : SqlMapper.TypeHandler<TimeSpan>
{
    public override TimeSpan Parse(object value)
    {
        return new TimeSpan((long)value);
    }

    public override void SetValue(IDbDataParameter parameter, TimeSpan value)
    {
        parameter.Value = value.Ticks;
    }
}

Voici mon POCO:

public class Task
{
    public TimeSpan Duration { get; set; }

    // etc.
}

Lors de l'exécution d'une simple instruction d'insertion comme celle-ci:

string sql = "INSERT INTO Tasks (Duration) values (@Duration);";

Et en passant le POCO comme objet à insérer:

Task task = new Task { Duration = TimeSpan.FromSeconds(20) };
connection.Execute(sql, task);

Je reçois cette exception:

System.InvalidCastException : Unable to cast object of type 'System.TimeSpan' to type 'System.IConvertible'.
   at System.Convert.ToInt64(Object value, IFormatProvider provider)
   at System.Data.SQLite.SQLiteStatement.BindParameter(Int32 index, SQLiteParameter param)
   at System.Data.SQLite.SQLiteStatement.BindParameters()
   at System.Data.SQLite.SQLiteCommand.BuildNextCommand()
   at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)
   at System.Data.SQLite.SQLiteDataReader.NextResult()
   at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
   at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, ref CommandDefinition command, Action`2 paramReader) in SqlMapper.cs: line 3310
   at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, ref CommandDefinition command) in SqlMapper.cs: line 1310
   at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType) in SqlMapper.cs: line 1185

Si je laisse le TimeSpan type TimeSpan tel quel (il DbType.Time défaut DbType.Time ), il écrit la version de chaîne de TimeSpan , c'est-à-dire 00: 00: 20.000, ce qui n'est pas utile car les autres données dans la colonne.

Réponse populaire

Pourriez-vous faire la suite à la place?

public class Task
{
    public TimeSpan Duration { get; set; }
    public long Ticks 
    { 
        get { return Duration.Ticks; }
        set { Duration = new TimeSpan(value); }
    }
    // etc.
}

string sql = "INSERT INTO Tasks (Duration) values (@Ticks);";


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi