2014-11-24 16 views
7

Tôi đang cố gắng sử dụng Dapper để giao diện với một định dạng cơ sở dữ liệu hiện có có một bảng có thời lượng được mã hóa thành các dấu tick trong cột BIGINT. Làm thế nào để tôi nói cho Dapper bản đồ thuộc tính POCO của 01OCO TimeSpan -typed để đánh dấu khi chèn vào và đọc từ cơ sở dữ liệu?Mapping TimeSpan trong SQLite và Dapper

Tôi đã cố gắng để thiết lập các bản đồ kiểu cho TimeSpan-DbType.Int64:

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

Và tôi cũng đã tạo một ITypeHandler, nhưng phương pháp SetValue không bao giờ được gọi là:

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

Dưới đây là POCO của tôi:

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

    // etc. 
} 

Wh en thực hiện một tuyên bố chèn đơn giản như thế này:

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

Và đi qua các POCO là đối tượng để chèn:

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

tôi nhận được ngoại lệ này:

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 

Nếu tôi rời khỏi TimeSpan loại ánh xạ như là (nó mặc định là DbType.Time), nó viết phiên bản chuỗi của TimeSpan, nghĩa là '00: 00: 20.000', không hữu ích vì nó không khớp với fo rmat của các dữ liệu khác trong cột.

+0

Tôi luôn giải quyết điều này bằng cách tạo ra một tài sản thứ hai làm dịch từ loại DB đến loại của tôi. – juharr

+0

Tại sao downvote ...? –

Trả lời

2

Bạn có thể thực hiện những việc sau thay thế không?

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

Tôi có thể, mặc dù là một newbie Dapper tôi đã hy vọng có một cái gì đó thư viện được cung cấp. Có vẻ như phải có tất cả các 'ITypeHandler' và các giao diện khác như vậy ... –

1

Giải pháp cho LinqToDB:

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

Hoặc:

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

Ví dụ:

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([email protected]"Id: {category.Id}, Time: {category.Time}"); 
     } 
    } 

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