SQLiteDataReader から読み取るときに、GetFieldType(0) が typeof(Int64) を返し、GetValue(0) が Int64 を返すという奇妙な動作が発生していますが、GetInt64(0) は System.InvalidCastException 例外で失敗します。
この動作を再現するのにかなり時間がかかりました:
using System;
using System.Data.SQLite;
using NUnit.Framework;
namespace Test
{
[TestFixture]
public class SQLiteType
{
[Test]
public void A()
{
var sqlConnection = new SQLiteConnection("Data Source=:memory:;Version=3;");
sqlConnection.Open();
var create = sqlConnection.CreateCommand();
create.CommandText = "CREATE TABLE FOO (x INTEGER)";
create.ExecuteNonQuery();
var insert = sqlConnection.CreateCommand();
insert.CommandText = "INSERT INTO FOO VALUES (?)";
var param = insert.CreateParameter();
param.Value = new TimeSpan(0); // NOTE INSERTING TIMESPAN DIRECTLY instead of .Ticks
insert.Parameters.Add(param);
insert.ExecuteNonQuery();
var select = sqlConnection.CreateCommand();
select.CommandText = "SELECT x FROM FOO";
var dr = select.ExecuteReader();
while (dr.Read())
{
var valueObject = dr.GetValue(0);
Assert.AreEqual(typeof (Int64), valueObject.GetType());
var valueType = dr.GetFieldType(0);
Assert.AreEqual(typeof (Int64), valueType);
var value = dr.GetInt64(0); // throws System.InvalidCastException
}
}
}
}
TimeSpan 値を INTEGER 列に直接挿入することによって行が作成されたときに発生するようです (たとえば、より意味のある TimeSpan.Ticks の代わりに)。それにもかかわらず、データリーダーは、列が Int64 であることをまだ伝えています。
SQLiteDataReader のコントラクトが正確にはわかりませんが、GetFieldType() が typeof(Int64) を返す場合、GetInt64() は失敗しないはずだと以前に想定していました。おそらくそうではないでしょうか?(GetValue() がまだ Int64 を返すのは非常に奇妙に思えます) おそらく、これは SQLite 独自の動的型付けシステムの成果物です。
確かに避けるのは難しいことではありませんが、教育上の理由から、なぜこれが起こっているのか気になります。