从 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 独特的动态类型系统的产物。
当然,这并不难避免,但出于教学原因,我只是好奇为什么会发生这种情况?