Umgang mit einem Datetime DBNull
Frage
Ich habe viele, viele Versionen von diesem auf SO gesehen, aber keiner von ihnen scheinen ziemlich Arbeit für meine Bedürfnisse.
kommt Meine Daten von einem Anbieter-Datenbank, die null für Datetime-Felder ermöglicht. Zunächst ziehe ich meine Daten in eine Datentabelle.
using (SqlCommand cmd = new SqlCommand(sb.ToString(), conn))
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
Ich bin ein Datatable in eine Liste konvertieren <> für die Verarbeitung.
var equipment = from i in dt.AsEnumerable()
select new Equipment()
{
Id = i.Field<string>("ID"),
BeginDate = i.Field<DateTime>("BeginDate"),
EndDate = i.Field<DateTime>("EndDate"),
EstimatedLife = i.Field<double>("EstimatedLife")
}
Also, wie kann ich überprüfen, für DBNull in diesem Fall? Ich habe versucht, ein Verfahren zu schreiben.
public DateTime CheckDBNull(object dateTime)
{
if (dateTime == DBNull.Value)
return DateTime.MinValue;
else
return (DateTime)dateTime;
}
Lösung
Eine mögliche Option ist speichern Sie es als eine Nullable-Datum Zeit mit der Syntax DateTime?
Hier ist ein Link auf die MSDN über die Verwendung von Nullable Types
Andere Tipps
Verwenden Sie IsDBNull()
System.Convert.IsDBNull(value);
oder wenn Sie eine SqlDataReader
reader.IsDBNull(ordinal);
Und Ihre DateTime
Eigenschaften machen nullable (DateTime?
) und Set null
bei DBNull
sein. Field<T>()
wird dies automatisch tun.
Hier ist ein Beispiel für einige Codes verwende ich Datetime lesen
Ich bin sicher, es könnte besser werden geschrieben, aber läuft gut für mich
public DateTime? ReadNullableDateTimefromReader(string field, IDataRecord data)
{
var a = data[field];
if (a != DBNull.Value)
{
return Convert.ToDateTime(a);
}
return null;
}
public DateTime ReadDateTimefromReader(string field, IDataRecord data)
{
DateTime value;
var valueAsString = data[field].ToString();
try
{
value = DateTime.Parse(valueAsString);
}
catch (Exception)
{
throw new Exception("Cannot read Datetime from reader");
}
return value;
}
Ich habe festgestellt, dass der einfachste Weg, dies zu handhaben ist, das Feld als Datentyp wirft das „als“ Schlüsselwort. Dies funktioniert gut für Datenbankfelder, die null sein kann, und ist schön und einfach.
Hier ist ausführlicher auf diese: Angießen vs ‚als‘ Operator
Beispiel:
IDataRecord record = FromSomeSqlQuerySource;
string nullableString;
DateTime? nullableDateTime;
nullableString = record["StringFromRecord"] as string;
nullableDateTime = record["DateTimeFromRecord"] as DateTime?;
Sie sollten DataRow["ColumnName"] is DBNull
verwenden Datetime null zu vergleichen.
Z. B:.
if(studentDataRow["JoinDate"] is DBNull) { // Do something here }
Ich schrieb eine generische Erweiterung Methode, die ich in all meinen Projekten verwenden:
public static object GetValueSafely<T>(this System.Data.DataTable dt, string ColumnName, int index)
{
if (typeof(T) == typeof(int))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return 0;
}
else if (typeof(T) == typeof(double))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return 0;
}
else if (typeof(T) == typeof(decimal))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return 0;
}
else if (typeof(T) == typeof(float))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return 0;
}
else if (typeof(T) == typeof(string))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return string.Empty;
}
else if (typeof(T) == typeof(byte))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return 0;
}
else if (typeof(T) == typeof(DateTime))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return DateTime.MinValue;
}
else if (typeof(T) == typeof(bool))
{
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return false;
}
if (dt.Rows[index][ColumnName] != DBNull.Value)
return dt.Rows[index][ColumnName];
else
return null;
}
Anwendungsbeispiel:
private void Example()
{
DataTable dt = GetDataFromDb() // get data from database...
for (int i = 0; i < dt.Rows.Count; i++)
{
Console.WriteLine((DateTime)dt.GetValueSafely<DateTime>("SomeDateColumn", i));
Console.WriteLine((int)dt.GetValueSafely<int>("SomeIntColumn", i));
Console.WriteLine((string)dt.GetValueSafely<string>("SomeStringColumn", i));
}
}