最有效的方法来检查DBNull的,然后分配给一个变​​量? [英] Most efficient way to check for DBNull and then assign to a variable?

查看:188
本文介绍了最有效的方法来检查DBNull的,然后分配给一个变​​量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题来了偶然,但我还没有看到一个满意的答案。

一个典型的模式是(行是一个的DataRow ):

 如果(行[价值]!=的DBNull.Value)
 {
      someObject.Member =行[值];
 }
 

我的第一个问题是,这是更有效的(我已经翻转的条件):

 行[价值] ==的DBNull.Value; // 要么
  行[价值]是的DBNull; // 要么
  行[价值]的GetType()== typeof运算(为DBNull)//还是......有什么建议?
 

表明.GetType()应该会更快,但也许编译器知道一些技巧我不?

第二个问题,是否值得缓存行的值[值]还是编译器优化索引离开呢?

例如:

 对象而ValueHolder;
  如果(==的DBNull.Value(而ValueHolder =行[价值])){}
 

注:

  1. 行[值]的存在。
  2. 在我不知道的列(因此列名查找)。
  3. 的列索引
  4. 我要问具体有关检查的DBNull,然后分配(不约premature优化,等等)。

我为基准几个方案(时间以秒为单位,10,000,000试验):

 行[价值] ==的DBNull.Value:00:00:01.5478995
行[价值]是为DBNull:00:00:01.6306578
行[价值]的GetType()== typeof运算(为DBNull):​​00:00:02.0138757
 

Object.ReferenceEquals具有相同的性能,==

最有趣的结果呢?如果通过案不匹配的列的名称(例如,值,而不是值,它需要大约10倍的时间(为一个字符串):

 行[价值] ==的DBNull.Value:00:00:12.2792374
 

这个故事的寓意似乎是,如果你不能抬头一列由它的索引,然后确保你喂到索引的列名的DataColumn的名称完全匹配。

缓存的价值似乎也接近两次作为快:

 无缓存:00:00:03.0996622
与高速缓存:00:00:01.5659920
 

因此​​,最有效的方法的似乎的是:

 对象温度;
 字符串变量;
 如果(的DBNull.Value!=(TEMP =行[价值]))
 {
      变量= temp.ToString();
 }
 

解决方案

我必须失去了一些东西。不检查的DBNull 正是 DataRow.IsNull 方法呢?

我一直在使用以下两种扩展方法:

 公共静态T'的GetValue< T>(此行的DataRow,串COLUMNNAME)其中T:结构
{
    如果(row.IsNull(COLUMNNAME))
        返回null;

    回行[COLUMNNAME]为T ?;
}

公共静态字符串的getText(此行的DataRow,串COLUMNNAME)
{
    如果(row.IsNull(COLUMNNAME))
        返回的String.Empty;

    回行[COLUMNNAME]为字符串?的String.Empty;
}
 

用法:

 诠释? ID = row.GetValue< INT>(ID);
字符串名称= row.GetText(姓名);
双?价格= row.GetValue<双>(价格);
 

如果你不想让可空< T> 返回值的GetValue< T> ,你可以很容易地返回默认(T)或其他选项。


在一个不相关的音符,这里有一个VB.NET替代Stevo3000的建议:

  oSomeObject.IntMember = IF(TryConvert(整数)(oRow(值)),iDefault)
oSomeObject.StringMember = IF(TryCast(oRow(姓名),字符串),sDefault)

功能TryConvert(对T作为结构)(OBJ BYVAL作为对象)为t?
    如果TypeOf运算obj是T接
        回到新的T'(DirectCast(OBJ,T))
    其他
        返回任何结果
    结束如果
端功能
 

This question comes up occasionally, but I haven't seen a satisfactory answer.

A typical pattern is (row is a DataRow):

 if (row["value"] != DBNull.Value)
 {
      someObject.Member = row["value"];
 }

My first question is which is more efficient (I've flipped the condition):

  row["value"] == DBNull.Value; // Or
  row["value"] is DBNull; // Or
  row["value"].GetType() == typeof(DBNull) // Or... any suggestions?

This indicates that .GetType() should be faster, but maybe the compiler knows a few tricks I don't?

Second question, is it worth caching the value of row["value"] or does the compiler optimize the indexer away anyway?

For example:

  object valueHolder;
  if (DBNull.Value == (valueHolder = row["value"])) {}

Notes:

  1. row["value"] exists.
  2. I don't know the column index of the column (hence the column name lookup).
  3. I'm asking specifically about checking for DBNull and then assignment (not about premature optimization, etc.).

I benchmarked a few scenarios (time in seconds, 10,000,000 trials):

row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757

Object.ReferenceEquals has the same performance as "=="

The most interesting result? If you mismatch the name of the column by case (for example, "Value" instead of "value", it takes roughly ten times longer (for a string):

row["Value"] == DBNull.Value: 00:00:12.2792374

The moral of the story seems to be that if you can't look up a column by its index, then ensure that the column name you feed to the indexer matches the DataColumn's name exactly.

Caching the value also appears to be nearly twice as fast:

No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920

So the most efficient method seems to be:

 object temp;
 string variable;
 if (DBNull.Value != (temp = row["value"]))
 {
      variable = temp.ToString();
 }

解决方案

I must be missing something. Isn't checking for DBNull exactly what the DataRow.IsNull method does?

I've been using the following two extension methods:

public static T? GetValue<T>(this DataRow row, string columnName) where T : struct
{
    if (row.IsNull(columnName))
        return null;

    return row[columnName] as T?;
}

public static string GetText(this DataRow row, string columnName)
{
    if (row.IsNull(columnName))
        return string.Empty;

    return row[columnName] as string ?? string.Empty;
}

Usage:

int? id = row.GetValue<int>("Id");
string name = row.GetText("Name");
double? price = row.GetValue<double>("Price");

If you didn't want Nullable<T> return values for GetValue<T>, you could easily return default(T) or some other option instead.


On an unrelated note, here's a VB.NET alternative to Stevo3000's suggestion:

oSomeObject.IntMember = If(TryConvert(Of Integer)(oRow("Value")), iDefault)
oSomeObject.StringMember = If(TryCast(oRow("Name"), String), sDefault)

Function TryConvert(Of T As Structure)(ByVal obj As Object) As T?
    If TypeOf obj Is T Then
        Return New T?(DirectCast(obj, T))
    Else
        Return Nothing
    End If
End Function

这篇关于最有效的方法来检查DBNull的,然后分配给一个变​​量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆