2016-05-20 12 views
6

W mojej bazie danych mam wartość NextStatDistanceTime jako float. Kiedy linia „float time = reader.GetFloat(0);” ścięci, daje błądJak uzyskać wartość zmiennoprzecinkową za pomocą SqlDataReader?

systemu

nieprawidłowej wyjątkiem szarego

Jak mogę uzyskać wartość pływaka z polecenia SQL w tym kodzie?

Oto mój kod:

using (SqlConnection conn = new SqlConnection(@"<myconnectionstring>")) 
{ 
    float totaltime = 0; 
    for (int i = startStationIndex; i < endStationIndex; i++) 
    { 
     SqlCommand command = new SqlCommand("SELECT NextStatDistanceTime FROM [MetroDatabase].[dbo].[MetroStation] WHERE StationIndex = " + i + "", conn); 
     try 
     { 
      conn.Open(); 
      command.ExecuteNonQuery(); 
      using (SqlDataReader reader = command.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        float time = reader.GetFloat(0); 
        totaltime = totaltime + time; 
        conn.Close(); 
       } 
      }       
     } 
     catch (Exception ex) 
     { 
      result = ex.Message; 
      Console.WriteLine(ex.Message); 
     } 
    } 

} 
+3

Jaki jest typ w bazie danych? –

+0

@JonSkeet wspomniał o tym, jego "float" w bazie danych. –

+1

@RanjitSingh: Ups, przegapiłem to. W takim przypadku naprawdę bym się spodziewał, że wszystko będzie dobrze ... Domyślam się, że to nie jest * tak naprawdę * zmienna w bazie danych. Byłoby interesujące poznać wynik wywołania 'reader.GetValue (0)' - jaki to jest typ? –

Odpowiedz

12

Nadszedł czas na stoliku, myślę.

T-SQL type name | .NET equivalent | C# type name | DataReader method 
----------------+-----------------+--------------+------------------------ 
FLOAT   | System.Double | double  | IDataReader.GetDouble() 
REAL   | System.Single | float  | IDataReader.GetFloat() 

Zauważ, że GetFloat ma złą nazwę - powinna być GetSingle, ponieważ float jest C# -specyficznych imię. W VB.NET nie ma to sensu.

Tak więc, jeśli kolumna bazy danych jest typu FLOAT, przeczytaj ją, używając GetDouble, a nie GetFloat. Metody odczytu danych nie wykonują konwersji; istnieje ogólna metoda GetValue, aby uzyskać wartość jako object, którą następnie można dalej przekształcać.

Nawiasem mówiąc, nie jest to jedyna subtelność -.Typy zmiennoprzecinkowe NET obsługują denormalized values, natomiast typy T-SQL nie, więc możliwe jest stosowanie liczb zmiennoprzecinkowych w kodzie .NET, których nie można pomyślnie zapisać w bazie danych, nawet jeśli typy są zgodne.

+0

Możesz znaleźć tabelę [tutaj] (https://msdn.microsoft.com/en-us/library/ms131092 (v = sql.130) .aspx) ;-) –

+0

@TimSchmelter: to jest subtelnie inna tabela, ponieważ opisuje mapowanie do typów specyficznych dla ADO.NET SQL. 'SqlSingle' nie jest tym samym, co' System.Single'. Mogę dołączyć go do mojej tabeli pod kątem kompletności, ale rzadko istnieje potrzeba korzystania z tych typów, chyba że nie ma odpowiedniego typu systemu .NET (np. 'SqlGeography'). Ale, tak, to kolejna warstwa konwersji, o których należy pamiętać. –

0

można spróbować:

float time = float.Parse(reader[0].ToString()); 

również zauważyć (choć nie związane z Q), że nie ma potrzeby uruchamiania

command.ExecuteNonQuery(); 
0
while (reader.Read()) 
{ 
    object initialTime = reader["NextStatDistanceTime"]; 
    float time; 
    float.TryParse(initialTime.ToString(), out time); 

    totaltime = totaltime + time; 
    conn.Close(); 
} 

Spróbuj tego, dostaniesz czas f z bazy danych, a następnie przekonwertuj ją na zmienną, możesz po prostu wstawić reader["NextStatDistanceTime] w tryparse, jeśli chcesz, ale żeby było wyraźniej, zrobiłem to w ten sposób.

Wszelkie problemy daj mi znać

+2

Jest to niepotrzebne obejście problemu. –

+0

@ TimSchmelter wyjaśnić? – Brendon

+0

Zobacz na przykład odpowiedź @Hari Prasad. Nie ma potrzeby wykonywania tej pracy. –

0

Spróbuj

convert.ToSingle(reader["NextStatDistanceTime"]) 

czy

double value = (double)reader["NextStatDistanceTime"] 

Float SQL jest równoważne podwoić z C#, można zobaczyć podobną mapowanie here

0

Prawdopodobnie jest to niedopasowanie precyzyjne między typem bazy danych a typem C#. Spróbuj rzucić jak (float)reader.GetDouble(0);

1

Domyślam się, że baza danych jest zwrócenie podwójna wartość, spróbuj się go jako Double i przekształcić go float (jeśli jest wymagane).

float time= (float) reader.GetDouble(0); 
3

Jak można przeczytać here do mapy pływaka sql-server do podwójnego .NET, więc trzeba użyć GetDouble:

double totaltime = 0; // necessary, double is wider than float 
// ... 

while (reader.Read()) 
{ 
    double time = reader.GetDouble(0); 
    totaltime = totaltime + time; 
    // conn.Close(); no, not in this loop, should be closed in the finally or via using-statement 
} 
Powiązane problemy