在 C# 中从 SQLite 数据库获取类型 REAL/DOUBLE 的值的好方法是什么
What are good ways to get values of type REAL/DOUBLE from a SQLite Database in C#
我正在尝试获取类型为 REAL 的特定列的值,并希望将其保存在 double 或 float 中.
问题是,到目前为止我所尝试的一切要么只返回一个整数,要么返回一个错误: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"));
我再次仔细检查了值是否已正确写入数据库。将它们作为 float 和 double 传入,当我使用
检查类型时
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 亲和力,并使用“.”而不是“,”作为小数点分隔符。
我正在尝试获取类型为 REAL 的特定列的值,并希望将其保存在 double 或 float 中.
问题是,到目前为止我所尝试的一切要么只返回一个整数,要么返回一个错误: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"));
我再次仔细检查了值是否已正确写入数据库。将它们作为 float 和 double 传入,当我使用
检查类型时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 亲和力,并使用“.”而不是“,”作为小数点分隔符。