如何使用 SqlDataReader 获取双倍值

How to get double value with SqlDataReader

我正在尝试从 sql 数据库中读取数据。当我 运行 代码时,它在读取数据的位置时出错。

"System.InvalidCastException: Specified cast is not valid."

我收到一个错误。我研究了我的错误,但找不到适合我的解决方案。虽然我编写的查询文本在 ssms 中有效,但在代码中不起作用。

 private void pbx_frame_MouseUp(object sender, MouseEventArgs e) //
    {
        //take cropped image to picture box of crooped images
        try
        {
            string[] resim = lbx_raw_image.SelectedItem.ToString().Replace(':','.').Split('.'); 
            string sorgu_sql = "Data Source=DESKTOP-OON7EET\SQLEXPRESS;Initial Catalog=Target;Integrated Security=True;"; //sql bağlantısı kuruldu
            //string query = "SELECT * FROM MP_Data$ WHERE time= '19.53.06'"; //'" + lbx_raw_image.SelectedItem.ToString() + "'"; //time=19.53.06 tek bir veriyi çağrır. muhtemelen yorum haline getirilen kısım olacaktı.
            string query = "SELECT * FROM MP_DATA_15_mayıs_2019$ WHERE time='" + lbx_raw_image.SelectedItem.ToString() + "'"; //12.50.23
            DB_islem db = new DB_islem(sorgu_sql, query); // 
            
            pic_info_from_MP = db.Raw_Image(pic_info_from_MP);      



    public Target Raw_Image(Target pic_info) 
    {
        sql.Open();
       
        sql_read = sql_command.ExecuteReader();

        //while (sql_read.Read())
        if (sql_read.Read())
        {
            pic_info.lat = sql_read.GetDouble(0);
            pic_info.lon = sql_read.GetDouble(1);
            pic_info.alt = sql_read.GetDouble(2);
            pic_info.yaw = sql_read.GetDouble(3);
        }

        sql.Close();

        return pic_info;
    }

解决方案:

ALTER TABLE table1(name of table) ALTER COLUMN clmn1(name of column) float(datatype);

我使用上述查询确定了每一列的数据类型。帮我调用了需要的数据。

首先,您应该仅使用参数执行查询。 其次,我们不知道您的 table 架构 - 请出示它。

但很可能您存储此值的方式存在问题。 GetDouble 不进行任何转换,因此您的数据应该已经保存为 double。

此外,全球化可能会出现问题。你应该做的是:

using System.Globalization;
//...

double result = double.NaN;

if(!sql_read.IsDbNull(0))
{
    string s = sql_read.GetString(0);
    result = Convert.ToDouble(s, CultureInfo.InvariantCulture);
} 

我要求 table 定义的原因是因为数据库端有特定的列类型映射到 C# 端的特定数据类型。发布的屏幕截图不足以实际确定列类型。纬度和经度不是 real,否则它们会被截断,但除此之外我们真的不能说

广义地说:

  • 如果您使用了 real 列类型,请调用 GetFloat(..)
  • 如果您使用了 float 列类型,请调用 GetDouble(..)
  • 如果您使用了 decimal(或 numeric)列类型,请调用 GetDecimal(..)

GetXxx 不会为您转换,因为它会进行拆箱转换。如果您的 reader 在第 0 列中有一个 decimal,您只能对其调用 GetDecimal。您不能调用 GetDouble 并期望您将真正的小数转换为双精度数,原因与这不起作用相同:

object o = 0.1m; //decimal boxed inside object
double d = (double)o;

拆箱转换和转换转换是不同的事情。如果您希望将对象中的小数作为双精度数,则必须进行两次转换,一次用于拆箱,一次用于转换:

object o = 0.1m; //decimalboxed inside object
double d = (double)(decimal)o;

同样,如果您在 reader 列 0 中的内容是 decimal,而您想要 double,则必须将其作为小数,因为它确实是小数,然后转换它:

var dbl = (double)reader.GetDecimal(0);

简单规则:

  • 按照原来的样子拉出来,然后转换

至于你有什么,我们不知道;您的 yaw 可能是 real 而不能 GetDouble(必须是 GetFloat)。您的 alt 可能是小数(您真的需要高度为 picometer/pico-ft 的十分之一吗?)并且不能 GetDouble'd(必须 GetDecimal'd) .. 但你有自己解决这个问题的所有必要信息。

如果所有其他方法都失败了,并且上面的内容完全超出了您的理解范围,请尝试将不起作用的行的 GetDouble 更改为 GetDecimal。如果这不起作用,请尝试将其更改为 GetFloat。如果那不起作用,请提供 table 定义,我们会告诉您它应该是什么

更新:您已经指出它们都是 varchar。就我个人而言,我会将它们转换为浮点数或真实数 - 打开 SSMS,设计 table,将列类型更改为例如浮点数并保存 table。然后他们可以GetDouble'd