2010-04-09 22 views
10

(LocalVariable) ABC.string (Name) = (Idatareader) datareader.GetString (0);Null bezpieczny sposób na uzyskanie wartości z IDataReader

ta wartość nazwy pochodzi z bazy danych .. co się tutaj dzieje, jeśli ta wartość nazwy jest pusta podczas odczytu jest rzucanie wyjątku?

Ręcznie robię niektóre warunek tutaj. Nie chcę napisać instrukcję, aby sprawdzić stan wszystkich moich zmiennych ..

robie coś takiego teraz ..

string abc = (Idatareader)datareader.GetValue(0); 
if(abc = null) 
    //assiging null 
else 
    assiging abc value 

czy istnieje coś takiego jak możemy napisać metodę rozszerzenia dla tego? dzięki

Odpowiedz

20

Oto kilka metod przedłużania że będzie ładnie zakończyć wszystkie swoje obawy wokół pobierania silnie wpisane wartości z czytnikiem danych. Jeśli wartość to DbNull, zostanie zwrócona wartość domyślna typu. W przypadku string, która jest klasą, zwracane jest null. Jeśli pole to jest int, zostanie zwrócone 0. Dodatkowo, jeśli oczekujesz, że int?, powiedzmy z zerowego pola int, zostanie zwrócony null.

Specyficzne dla przypadku użycia Kumara:

string abc = datareader.GetValueOrDefault<string>(0); 

przeznaczeniem

var name = GetValueOrDefault<string>(reader, "Name"); 

lub

var name = reader.GetValueOrDefault<string>("Name"); 

lub

var name = reader.GetValueOrDefault<string>(0); 

Extension

public static class NullSafeGetter 
{ 
    public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName) 
    { 
     int ordinal = row.GetOrdinal(fieldName); 
     return row.GetValueOrDefault<T>(ordinal); 
    } 

    public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal) 
    { 
     return (T)(row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal)); 
    } 
} 

z http://skysanders.net/subtext/archive/2010/03/02/generic-nullsafe-idatarecord-field-getter.aspx

+0

W przypadku, gdy wartość jest DBNull i spodziewamy się int, czy nie jest tak źle, aby po prostu zwrócić 0? Czy nie powinniśmy w tym przypadku wyrzucić wyjątku, ponieważ coś jest oczywiście nie tak - albo powinniśmy się spodziewać int? lub zapytanie powoduje błędny typ wartości? Umieszczenie 0 w miejscu, w którym nie ma rzeczywistej wartości, może być w niektórych przypadkach w porządku, ale myślę, że posiadanie tego w powszechnie używanej bibliotece może prowadzić do bardzo subtelnych błędów. – poke

+0

To wygodne, aby móc przekazać wartość domyślną jako parametr: 'public static T GetValueOrDefault (ten wiersz IDataRecord, int ordinal, T defaultValue = default (T))' – mistika

+0

@Poke dla przypadku int, który chcesz mieć T 'int?', więc zwracana wartość może być pusta. –

0

chciałbym użyć czegoś takiego:

string abc = (IDataReader)datareader.GetValue(0) ?? "Default"; 
+0

co zamierza zrobić? możesz wyjaśnić mi dziękuję – kumar

+0

"Operator ?? jest nazywany operatorem koalescencyjnym i jest używany do definiowania wartości domyślnej dla typów wartości zerowych, jak również typów referencyjnych, zwraca lewy operand, jeśli nie jest zerowy; w przeciwnym razie zwraca prawy operand. " http://msdn.microsoft.com/en-us/library/ms173224.aspx – Powerlord

+2

Przetestowałeś to, ponieważ 'DbNull! = null' –

2

moje rozwiązanie jest to, że:

private static T GetValue<T>(object o) { 
    if (typeof(DBNull) != o.GetType()) { 
     return (T) o; 
    } 
    return default(T); 
} 

Kiedy Status = GetValue<string>(currentDataRow["status"])

+4

Zamiast używać funkcji typeof() i GetType(), nie można tego zrobić: "if (o is DBNull)". Moim zdaniem jest bardziej czytelny. – JMS10

+2

Co jest nie tak z 'if (o == DBNull.Value)? –

+0

Szanse są "o == DBNull.Value" jest szybsze niż 'o jest DBNull', a najbardziej na pewno niż' typeof (DBNull)! = O.GetType() '. – nawfal

3

podobne do @ sky-Sanders odpowiedź ale mniej ścisłe z konwersji:

public static T Get<T>(this IDataRecord row, string fieldName) 
{ 
    int ordinal = row.GetOrdinal(fieldName); 
    return row.Get<T>(ordinal); 
} 

public static T Get<T>(this IDataRecord row, int ordinal) 
{ 
    var value = row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal); 
    return (T)Convert.ChangeType(value, typeof(T)); 
} 
1

Łącząc najlepsze rozwiązania i sugestie, oto C# 6 wyrażenie strzałki wersja z obsługą GetValue<T> i GetValueOrDefault<T> z opcjonalnymi domyślnymi parametrami wartości.

public static class DataRecordExtensions { 
    /// <summary> 
    /// Generically extracts a field value by name from any IDataRecord as specified type. Will throw if DNE. 
    /// </summary> 
    public static T GetValue<T>(this IDataRecord row, string fieldName) 
     => row.GetValue<T>(row.GetOrdinal(fieldName)); 

    /// <summary> 
    /// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will throw if DNE. 
    /// </summary> 
    public static T GetValue<T>(this IDataRecord row, int ordinal) 
     => (T)row.GetValue(ordinal); 

    /// <summary> 
    /// Generically extracts a field value by name from any IDataRecord as specified type. Will return default generic types value if DNE. 
    /// </summary> 
    public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName, T defaultValue = default(T)) 
     => row.GetValueOrDefault<T>(row.GetOrdinal(fieldName), defaultValue); 

    /// <summary> 
    /// Generically extracts a field value by ordinal from any IDataRecord as specified type. Will return default generic types value if DNE. 
    /// </summary> 
    public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal, T defaultValue = default(T)) 
     => (T)(row.IsDBNull(ordinal) ? defaultValue : row.GetValue(ordinal)); 
}