【问题标题】:What are good ways to get values of type REAL/DOUBLE from a SQLite Database in C#什么是从 C# 中的 SQLite 数据库中获取 REAL/DOUBLE 类型值的好方法
【发布时间】:2021-07-11 03:39:26
【问题描述】:

我正在尝试获取具有 REAL 类型的特定列的值,并希望将其保存在 doublefloat 中。 p>

问题是,到目前为止,我尝试的所有操作要么只返回一个整数,要么返回一个错误:指定的转换无效。例如,如果数据库中的值为 1,99,我会得到 1。调试器说它仍然是 double 类型。

我尝试过的:

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

我实际上尝试了更多组合,但都没有奏效。 我期待

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

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

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

但双打似乎给我带来了很多麻烦。

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

【问题讨论】:

  • 我认为您遇到了小数点中逗号而不是句点的文化问题。在使用 System.Convert.ToDouble 转换字符串之前,您是否尝试将逗号替换为句点? System.Convert.ToDouble(sqlReader["KDRatio"].Replace(",",".")) 之类的东西?
  • sqlReader["KDRatio"].GetType().Name的实际数据类型是什么?
  • @TamBui 刚刚试过,但又只给了我一个整数
  • @Charlieface 是双份的。
  • 你能分享异常“Specified cast not valid”的堆栈跟踪吗?你怎么知道来自(double)sqlReader["KDRatio"]的结果是错误的,你真的用另一种方式检查过数据库吗?

标签: c# sqlite double sqldatareader


【解决方案1】:

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

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

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,那么value 是用句号写的,我可以使用 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")); }

【讨论】:

    【解决方案2】:

    这似乎是 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 关联,并使用“。”而不是“,”作为小数点分隔符。

    【讨论】:

    • 啊,是的,我也用这些想法对我的答案进行了编辑。我可能会重新定义该列。那么,有可能喜欢强制它使用特定的分隔符吗?我还是 sql 的新手,但我会研究一下。谢谢提示
    猜你喜欢
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2014-03-06
    相关资源
    最近更新 更多