簡體   English   中英

在SQLite和Dapper中映射TimeSpan

[英]Mapping TimeSpan in SQLite and Dapper

我正在嘗試使用Dapper連接到現有數據庫格式,該數據庫格式的表的持續時間編碼為BIGINT列中的刻度。 在插入數據庫或從數據庫讀取數據時,如何告訴Dapper將POCO的TimeSpan類型的屬性映射到刻度線?

我試圖將TimeSpan的類型映射設置為DbType.Int64

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

而且我還創建了一個ITypeHandler ,但是從未調用SetValue方法:

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;
    }
}

這是我的POCO:

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

    // etc.
}

執行這樣的簡單插入語句時:

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

並將POCO作為要插入的對象:

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

我得到這個例外:

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

如果我按原樣保留TimeSpan類型映射(默認為DbType.Time ),它將寫入TimeSpan的字符串版本,即`00:00:20.000“,這與它的格式不匹配沒有幫助。列中的其他數據。

您可以代替以下方法嗎?

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);";

LinqToDB解決方案:

MappingSchema.SetDataType(typeof(TimeSpan), DataType.NText);

要么:

MappingSchema.SetDataType(typeof(TimeSpan), DataType.Int64);

例:

    public class Program
{
    private const string ConnectionString = "Data Source=:memory:;Version=3;New=True;";

    public static void Main()
    {
        var dataProvider = new SQLiteDataProvider();

        var connection = dataProvider.CreateConnection(ConnectionString);
        connection.Open();

        var dataConnection = new DataConnection(dataProvider, connection);

        dataConnection.MappingSchema.SetDataType(typeof(TimeSpan), DataType.Int64);

        dataConnection.CreateTable<Category>();

        dataConnection.GetTable<Category>()
            .DataContextInfo
            .DataContext
            .Insert(new Category
            {
                Id = 2,
                Time = new TimeSpan(10, 0, 0)
            });


        foreach (var category in dataConnection.GetTable<Category>())
        {
            Console.WriteLine($@"Id: {category.Id}, Time: {category.Time}");
        }
    }

    private class Category
    {
        public int Id { get; set; }
        public TimeSpan Time { get; set; }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM