tipos - ¿Por qué un flotador SQL es diferente de un flotador C#
sql server data types c# equivalents (6)
Hola, tengo un DataRow sacado de una DataTable de un DataSet. Estoy accediendo a una columna que está definida en SQL como un tipo de datos flotante. Intento asignar ese valor a una variable local (tipo de datos flotante c #) pero obtengo un InvalidCastExecption
DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];
Ahora, jugando con esto, lo hice funcionar, pero no tenía ningún sentido y no me sentía bien.
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
¿Alguien puede explicar lo que me falta aquí?
El flotante en Microsoft SQL Server es equivalente a un doble en C #. La razón para esto es que un número de coma flotante solo puede aproximarse a un número decimal, la precisión de un número de coma flotante determina con qué precisión ese número se aproxima a un número decimal. El tipo doble representa un número de coma flotante de 64 bits de doble precisión con valores que van desde 1.79769313486232e308 negativo a 1.79769313486232e308 positivo, así como cero positivo o negativo, afinidad positiva, indefinición negativa y no-número (NaN).
Un flotante SQL es un doble según la documentación de SQLDbType .
Un flotante en SQL es un doble en el CLR (C # / VB). Hay una tabla de tipos de datos SQL con los equivalentes de CLR en MSDN.
Y normalmente nunca querrá usar float en SQL Server (o real) si planea realizar cálculos matemáticos en los datos ya que es un tipo de datos inexacto e introducirá errores de cálculo. Use un tipo de datos decimal en su lugar si necesita precisión.
Creo que la pregunta principal ha sido respondida aquí, pero me siento obligado a agregar algo para la sección de la pregunta que dice que esto funciona.
_AccelLimit = (float) (double) exercise ["DefaultAccelLimit"];
La razón por la que esto "funciona" y la razón por la que "no se siente bien" es que estás degradando el doble a una carroza por el segundo elenco (el de la izquierda), así que estás perdiendo precisión y diciéndole al compilador que está bien para truncar el valor devuelto.
En palabras, esta línea dice ... Obtener un objeto (que en este caso contiene un doble) Emitir el objeto en un doble (perder todo el ajuste del objeto) Emitir el doble en un flotante (perdiendo toda la precisión fina de un doble)
por ejemplo, si el valor es, por ejemplo, 0.0124022806089461 y usted hace lo anterior, entonces el valor de AccelLimit será 0.01240228
como ese es el alcance de lo que puede obtener un flotador en c # del doble valor. Es algo peligroso de hacer y estoy bastante seguro de que es un truncamiento también en lugar de un redondeo, pero alguien puede querer confirmar esto ya que no estoy seguro.
La razón por la que "no se siente bien" es porque C # usa la misma sintaxis para desempaquetar y para emitir , que son dos cosas muy diferentes. exercise["DefaultAccelLimit"]
contiene un valor doble, encuadrado como un objeto. (double)
es necesario para volver a poner el objeto en un doble. El (float)
al frente de eso arroja el doble a un valor flotante. C # no permite el boxeo y el casting en la misma operación, por lo que debes desempaquetar y luego lanzar.
Lo mismo es cierto incluso si el elenco no es destructivo. Si un flotador estaba encuadrado como un objeto que deseaba convertir en un doble, lo haría de la siguiente manera: (double)(float)object_var
.