在 C# 中从 SQLite 数据库获取类型 REAL/DOUBLE 的值的好方法是什么

What are good ways to get values of type REAL/DOUBLE from a SQLite Database in C#

我正在尝试获取类型为 REAL 的特定列的值,并希望将其保存在 doublefloat 中.

问题是,到目前为止我所尝试的一切要么只返回一个整数,要么返回一个错误:specified cast is not valid.例如,如果数据库中的值为 1,99,我会得到 1。调试器说它仍然是双精度类型。

我尝试过的:

public static void GetDouble()
{
    SQLiteConnection databaseConnection = new SQLiteConnection($"Data Source=.\val.sqlite;Version=3;");
    SQLiteCommand sqlCommand = databaseConnection.CreateCommand();
    sqlCommand.CommandText = $"SELECT * FROM doubles";
    databaseConnection.Open();

    SQLiteDataReader sqlReader = sqlCommand.ExecuteReader();
    while (sqlReader.Read())
    {
        // expected values: 1,1 | 8,66 | 0,64 | 0,82 | 1,9 | 0,89 | 0,52 | 1,35 | 4,32 | 1,66

        double nbr = (double)System.Convert.ToDouble(sqlReader["KDRatio"]); // gives me: 1 | 8 | 0 | 0 | 1 | 0 | 0 | 1 | 4 | 1

        // double nbr = sqlReader.GetDouble(sqlReader.GetOrdinal("KDRatio")); // specified cast is not valid
        // double nbr = sqlReader.GetDouble(5); // specified cast is not valid
        // double nbr = (double)sqlReader["KDRatio"]; // gives me: 1 | 8 | 0 | 0 | 1 | 0 | 0 | 1 | 4 | 1
        // float nbr = (float)sqlReader["KDRatio"]; // specified cast is not valid
        // float nbr = (float)System.Convert.ToDouble(sqlReader["KDRatio"]); // gives me: 1 | 8 | 0 | 0 | 1 | 0 | 0 | 1 | 4 | 1
        // string nbr = ((double)sqlReader.GetDouble(5)).ToString("#,#", CultureInfo.InvariantCulture); // specified cast is not valid

        System.Console.WriteLine(nbr);
    }
    databaseConnection.Close();
}

实际上我尝试了很多组合,但 none 奏效了。 我预计

double nbr = (double)System.Convert.ToDouble(sqlReader["KDRatio"]);

工作,因为在其他方法中我收到不同的值,例如

Name = sqlReader["Name"].ToString()
OnlineTimeMinutes = System.Convert.ToInt32(sqlReader["OnlineTimeMinutes"])

但是双打好像给我带来了很多麻烦

那么我怎样才能得到带两位小数的正确值呢?

好吧,两天后我弄明白了。然而,我觉得这不是(或不应该)是正确的方法。

这个,也只有这个,返回了正确的值。

sqlReader.GetString(sqlReader.GetOrdinal("KDRatio"));

我再次仔细检查了值是否已正确写入数据库。将它们作为 floatdouble 传入,当我使用

检查类型时
System.Console.WriteLine(sqlReader["KDRatio"].GetType().Name);

它在两种情况下都返回“Double”。

很奇怪,我不能像预期的那样使用 reader.GetFloat()reader.GetDouble() 吗?在我看来,读取双精度数或浮点数的唯一方法是将其作为字符串读取,这对我来说似乎是一个错误。不管怎样,现在可以了。

最终使用了这个:

double n = double.Parse(sqlReader.GetString(sqlReader.GetOrdinal("KDRatio")));

编辑:

纯属偶然发现了一些东西。我使用 DB Browser 检查数据库中的值,我注意到数据库中的值是否在小数部分只有 00's,例如 74.00 ,然后这个值是用句点写的,我可以使用 GetDouble() 就好了。 GetString() 然后会再次给我一个异常,转换无效。如果它那里还有其他东西,那么74,32,那么它是用逗号写的,我只能把它当作一个字符串来读。

这可能是 SQLite's Dynamic Typing 发挥作用的地方。它可能会弄乱我传入的双精度并且正在改变类型或其他东西。没有解释为什么当我检查时我仍然得到双重返回作为类型,但有趣的行为..

所以,现在我最终使用了这个:

double n;
try { n = double.Parse(sqlReader.GetString(sqlReader.GetOrdinal("KDRatio"))); }
catch { n = sqlReader.GetDouble(sqlReader.GetOrdinal("KDRatio")); }

这似乎是 SQLite 特性的某种组合——即类型亲和性、灵活的类型及其对数字文字的处理(忽略文化并需要“.”作为小数点分隔符)。

https://sqlite.org/datatype3.html#type_affinity

https://sqlite.org/quirks.html#flexible_typing

https://sqlite.org/lang_expr.html#literal_values_constants_

您的专栏可能具有文本亲和力。当您尝试将它们作为数字读取并遇到“,”字符时,SQLite.NET 库可能正在执行截断。

为了避免您当前的解决方法,我会尝试重新定义 SQLite 中的列以确保它是 NUMERIC 或 REAL 亲和力,并使用“.”而不是“,”作为小数点分隔符。