2013-05-20 7 views
20

Chcę pobrać 1. wiersz wartości pierwszej komórki z bazy danych, działa dobrze z poniżej kodu. Ale gdy nie znaleziono żadnego wyniku, rzuca wyjątek.Wartość powrotna za pomocą wyniku String = Błąd Command.ExecuteScalar() występuje, gdy wynik zwraca null

Sposób postępowania z DBNull.
Czy powinienem zmienić moje zapytanie? które zwracają pewną wartość, jeśli nie mają żadnego rekordu?

System.NullReferenceException: Odniesienie do obiektu nie jest ustawione na wystąpienie obiektu.

Kod:

public string absentDayNo(DateTime sdate, DateTime edate, string idemp) 
    { 
     string result="0"; 
     string myQuery="select COUNT(idemp_atd) absentDayNo from td_atd where "; 
     myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" "; 
     myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd "; 

     SqlCommand cmd = new SqlCommand(myQuery, conn); 
     conn.Open(); 
//System.NullReferenceException occurs when their is no data/result 
     string getValue = cmd.ExecuteScalar().ToString(); 
     if (getValue != null) 
     { 
      result = getValue.ToString(); 
     } 
     conn.Close(); 
     return result; 
    } 
+1

Gdzie zgłasza wyjątek? –

+1

Wyjątek wyrzuca 'ciąg getValue = cmd.ExecuteScalar(). ToString();' średni błąd występuje, gdy ich nie ma wyniku –

+4

btw, to jest ** naprawdę ** zły sposób na zbudowanie zapytania; wyraźny i rażący otwór wtryskowy sql; istnieje również problem internacjonalizacji i niektóre niepotrzebne ciągi pośrednie. Mam nadzieję, że to nie jest tak, jak zrobić sql normalnie ... –

Odpowiedz

44

Nie ma potrzeby, aby utrzymać nazywając .ToString() jak getValue jest już ciąg znaków.

Poza tym, ta linia mogłaby być problem:

string getValue = cmd.ExecuteScalar().ToString(); 

Jeśli nie ma wierszy .ExecuteScalar wróci null więc trzeba zrobić jakąś kontrolę.

Na przykład:

var firstColumn = cmd.ExecuteScalar(); 

if (firstColumn != null) { 
    result = firstColumn.ToString(); 
} 
+0

dzięki temu działa dobrze, również odpowiedź Naresha Parmara zadziałała dla mnie, dodając opcję sprawdzenia ciągu znaków "" –

+1

lub możesz użyć 'Convert.ToString (cmd.ExecuteScalar());' - to da ci 'String.Empty' if if wartość to 'null'. – DrNachtschatten

5

można używać jak na poniższym

string result = null; 
object value = cmd.ExecuteScalar(); 
if (value != null) 
{ 
    result = value.ToString(); 
}  
conn.Close(); 
return result; 
+1

@Satindersingh gdzie próbowałeś? z jakiego kodu korzystałeś? kod w pytaniu nie pokazuje tego ... –

+0

Tak, to powinno działać. –

+0

tak to również działa, przepraszam za poprzednie cmnt –

2

spróbuj tego:

string getValue = Convert.ToString(cmd.ExecuteScalar()); 
1

To powinno działać:

var result = cmd.ExecuteScalar(); 
conn.Close(); 

return result != null ? result.ToString() : string.Empty; 

Również sugeruję pomocą parametrów w zapytaniu, coś takiego (tylko sugestia):

var cmd = new SqlCommand 
{ 
    Connection = conn, 
    CommandType = CommandType.Text, 
    CommandText = "select COUNT(idemp_atd) absentDayNo from td_atd where absentdate_atd between @sdate and @edate and [email protected] group by idemp_atd" 
}; 

cmd.Parameters.AddWithValue("@sdate", sdate); 
cmd.Parameters.AddWithValue("@edate", edate); 
// etc ... 
9

Wypróbuj ten jeden

var getValue = cmd.ExecuteScalar();  
conn.Close(); 
return (getValue == null) ? string.Empty : getValue.ToString(); 
15

Jeżeli pierwsza komórka zwrócony jest null wynik w NET będzie DBNull.Value

Jeśli bez komórek są zwracane wynik w NET będzie null; nie można zadzwonić pod numer ToString() na numer null. Oczywiście można przechwycić to, co ExecuteScalar wraca i przetwarzać osobno.

Ponieważ grupujesz etc, prawdopodobnie masz potencjalnie więcej niż jedną grupę. Szczerze mówiąc nie jestem pewien, czy ExecuteScalar to najlepsza opcja tutaj ...


dodatkowe: sql w tej kwestii jest złe na wiele sposobów:

  • SQL injection
  • umiędzynarodowienie (miejmy nadzieję, że klient i serwer zgadzają się co data wygląda)
  • niepotrzebne konkatenacji w oddzielnych oświadczeniach

Gorąco polecam sparametryzować; Być może coś jak „Dapper” zrobić to proste:

int count = conn.Query<int>(
    @"select COUNT(idemp_atd) absentDayNo from td_atd 
    where absentdate_atd between @sdate and @edate 
    and [email protected] group by idemp_atd", 
    new {sdate, edate, idemp}).FirstOrDefault(); 

wszystkie problemy rozwiązane, w tym „nie wiersze” scenariusza. Daty są przekazywane jako daty (nie jako ciągi); otwór wtryskowy zamyka się za pomocą parametru. Otrzymasz ponowne wykorzystanie planu zapytań jako dodatkowy bonus. group by jest tutaj zbędny, BTW - jeśli istnieje tylko jedna grupa (przez warunek równości), równie dobrze możesz wybrać COUNT(1).

+0

Dzięki za miłe wytłumaczenie, po raz pierwszy usłyszałem o 'dapper', ucz się dziś nowego –

+1

@Sindindersingh jest on dostępny bezpłatnie na nuget: https://www.nuget.org/packages/Dapper –

4

Wartość nie jest pusta, ale wartość DBNull.Value.

object value = cmd.ExecuteScalar(); 
if(value == DBNull.Value) 
-1

Aby pracować z NpgsqlCommand lub standardowego użytkowania SQLCommand:

int result = int.Parse(cmd.ExecuteScalar().ToString()); 
0

użycie SQL Funkcja serwera IsNull

public string absentDayNo(DateTime sdate, DateTime edate, string idemp) 
{ 
    string result="0"; 
    string myQuery="select isnull(COUNT(idemp_atd),0) as absentDayNo from td_atd where "; 
    myQuery +=" absentdate_atd between '"+sdate+"' and '"+edate+" "; 
    myQuery +=" and idemp_atd='"+idemp+"' group by idemp_atd "; 

    SqlCommand cmd = new SqlCommand(myQuery, conn); 
    conn.Open(); 
    //System.NullReferenceException occurs when their is no data/result 
    string getValue = cmd.ExecuteScalar().ToString(); 
    if (getValue != null) 
    { 
     result = getValue.ToString(); 
    } 
    conn.Close(); 
    return result; 
} 
0

próbować ten jeden, jeśli zerowy ustawiony 0 lub coś

return command.ExecuteScalar() == DBNull.Value ? 0 : (double)command.ExecuteScalar(); 
Powiązane problemy