1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Dapper+SQLiteで自動型変換のエラーの対処法をgithubに投稿しました。

Posted at

dotnet core 2.1でコンソールアプリケーションの勉強中に出くわしたので、せっかくなので公開しときます。
Dapper+SQLiteで快適に使っていたのですが、なぜかdouble?型への型変換が特定の条件で失敗してしまいます。恐らく他の型でもありえるエラーでしょう。
具体的には以下のようなエラーが発生します。double?型を使ってほしいのですが、勝手にInt32型と判断しているのですね。

Unhandled Exception: System.Data.DataException: Error parsing column 1 (Column2=36 - Double) ---> System.InvalidCastException: Unable to cast object of type 'System.Double' to type 'System.Int32'.

SQLによっては発生しないらしく、order by の昇順降順を変更するだけでエラーが発生しなくなったりします。ややこしいエラーです。

対処法は SqlMapper の型別のハンドラを追加してあげる事です。以下の行をコメント解除する事でエラーが発生しなくなります。
SqlMapper.AddTypeHandler(typeof(System.Double),new DoubleConverter());

以下のページでも話題になっていました。
https://qrunch.net/@maccyo/entries/toOHtxzaj3Dy4QEp
https://github.com/StackExchange/Dapper/issues/642#issuecomment-435277926

1つ目のURLに解決方法が記載されているのですが、スペルの誤りがありましたので、せっかくですからちゃんと動く物をgithubに追加しておきました。
https://github.com/currysita/DapperCastErrorSample

ソース全文を以下に記載しときます。

Program.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using Dapper;
using Microsoft.Data.Sqlite;
using Models.Dapper.Mapper;

namespace dapperSample
{
    class HogeEntity {
        public double? Column1 {get;set;}
        public double? Column2 {get;set;}
    }
    class Program
    {
        static void Main(string[] args)
        {
            // SqlMapper.AddTypeHandler(typeof(System.Double),new DoubleConverter());
            var sqlConnectionSb = new SqliteConnectionStringBuilder { DataSource = "sqlitedb.sqlite3" };
            using(var con = new SqliteConnection(sqlConnectionSb.ToString())){
                try{
                    con.Execute("drop table Hoge;");
                }catch{}
                var createSql = $@"create table if not exists Hoge (
                    column1 REAL,
                    column2 REAL
                    )";
                con.Execute(createSql);
                var insertSql = "insert into Hoge (column1,column2 ) values (1,36)";
                con.Execute(insertSql);
                insertSql = "insert into Hoge (column1,column2 ) values (2,NULL)";
                con.Execute(insertSql);
                insertSql = "insert into Hoge (column1,column2 ) values (3,36)";
                con.Execute(insertSql);
                var list = con.Query<HogeEntity>(
                    "select column1 Column1 ,column2 Column2 from Hoge where column1 in @Column1 order by column2 IS NULL DESC"
                    ,new {Column1=new List<int>{1,2,3}});
                foreach(var hoge in list){
                    Console.WriteLine(hoge.Column1);
                    Console.WriteLine(hoge.Column2);
                }
            }
        }
    }
}

namespace Models.Dapper.Mapper{  
    public class DoubleConverter : SqlMapper.TypeHandler<double>{  
        public override Double Parse (Object value)  
        {  
            return Convert.ToDouble(value);  
        }  
        public override void SetValue(IDbDataParameter parameter, double value){  
            parameter.Value = value;  
        }  
    }
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?