[英]Handle DBNull in C#
有沒有更好/更清潔的方法來做到這一點?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
最短的(恕我直言)是:
int stockvalue = (reader["StockValue"] as int?) ?? 0;
解釋:
我處理這個的方式是
int? stockvalue = reader["StockValue"] as int?;
非常簡單,干凈,一行。 如果由於某種原因我絕對不能有一個空值(我發現通常情況下推理很糟糕,因為我寧願知道一個值是否有意義或者它是否為原始類型進行了單元化),我會這樣做:
int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
前幾天寫了一個擴展方法。 通過使用它,您可以執行以下操作:
int? stockvalue = reader.GetValue<int?>("StockValue");
這是擴展方法(根據您的需要進行修改):
public static class ReaderHelper
{
public static bool IsNullableType(Type valueType)
{
return (valueType.IsGenericType &&
valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}
public static T GetValue<T>(this IDataReader reader, string columnName)
{
object value = reader[columnName];
Type valueType = typeof(T);
if (value != DBNull.Value)
{
if (!IsNullableType(valueType))
{
return (T)Convert.ChangeType(value, valueType);
}
else
{
NullableConverter nc = new NullableConverter(valueType);
return (T)Convert.ChangeType(value, nc.UnderlyingType);
}
}
return default(T);
}
}
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);
一種可能的解決方案,以便您確保 DBNull 傳遞到您的代碼。 對於我們的小組,作為最佳實踐,我們盡量不允許數據庫中出現 NULL 列,除非確實需要。 處理它的編碼有更多的開銷,有時只是重新思考問題就不需要了。
是的,您可以使用int?
通過這種方式,您可以使用默認值 null 而不是 0。由於 stockvalue 的結果可能為 0,因此不會混淆數據庫是 0 還是 null。 例如像這樣(pre nullable),我們有一個默認的初始化 -1 來表示沒有分配任何值。 就我個人而言,我認為這有點危險,因為如果您忘記將其設置為 -1,則存在一個很難追蹤的數據損壞問題。
http://msdn.microsoft.com/en-us/library/2cf62fcy(VS.80).aspx
int? stockvalue = null;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
//Then you can check
if(stockValue.HasValue)
{
// do something here.
}
雖然引用reader["StockValue"]
很方便,但效率不高。 它也不是強類型的,因為它返回類型object
。
相反,在您的代碼中,執行以下操作:
int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
null :
reader.GetInt32(stockValueOrdinal);
當然,最好一次獲取所有序數,然后在整個代碼中使用它們。
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
這是一種方法。
int stockvalue = Convert.IsDbNull(reader["StockValue"]) ? 0 : (int)reader["StockValue"];
你也可以使用 TryParse
int stockvalue = 0
Int32.TryParse(reader["StockValue"].ToString(), out stockvalue);
讓我們知道哪種方式適合您
您可以直接在您的數據庫查詢中進行這種轉換,從而完全避免這種特殊情況。
但我不會稱其為“更干凈”,除非您可以在代碼中始終使用該表單,因為從數據庫返回“0”而不是 NULL 會丟失信息。
使用Nullable<int>
類型... int?
簡稱
並不真地。 您可以將其封裝在一個方法中:
public int getDBIntValue(object value, int defaultValue) {
if (!Convert.IsDBNull(value)) {
return (int)value;
}
else {
return defaultValue;
}
並這樣稱呼它:
stockVaue = getDBIntVaue(reader["StockValue"], 0);
或者您可以在查詢中使用coalesce
強制返回的值非空。
編輯 - 根據收到的評論更正愚蠢的代碼錯誤。
我的項目中有以下兩種擴展方法:
public static T GetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor)
where T : class
{
T value;
if (dataReader.TryGetValueSafe(columnName, valueExtractor, out value))
{
return value;
}
return null;
}
public static bool TryGetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor, out T value)
{
int ordinal = dataReader.GetOrdinal(columnName);
if (!dataReader.IsDBNull(ordinal))
{
// Get value.
value = valueExtractor.Invoke(dataReader, ordinal);
return true;
}
value = default(T);
return false;
}
用法可以是這樣的:
string companyName = dataReader.GetValueSafe("CompanyName", (reader, ordinal) => reader.GetString(ordinal));
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.