以下代码给出了一个错误 - "没有从DBnull到int的隐式转换".
SqlParameter[] parameters = new SqlParameter[1];
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;
parameters[0] = planIndexParameter;
Run Code Online (Sandbox Code Playgroud) 这个问题偶尔出现,但我没有看到一个满意的答案.
典型的模式是(row是DataRow):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是哪个更有效率(我翻了条件):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Run Code Online (Sandbox Code Playgroud)
这表明.GetType()应该更快,但编译器可能知道一些我不知道的技巧?
第二个问题,是否值得缓存row ["value"]的值,或者编译器是否优化了索引器?
例如:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Run Code Online (Sandbox Code Playgroud)
笔记:
我对几个场景进行了基准测试(时间以秒为单位,10,000,000次试验):
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
Run Code Online (Sandbox Code Playgroud)
Object.ReferenceEquals与"=="具有相同的性能
最有趣的结果?如果您不匹配逐列的名称(例如,"值"而不是"值",则大约需要十倍的时间(对于字符串):
row["Value"] == DBNull.Value: 00:00:12.2792374
Run Code Online (Sandbox Code Playgroud)
故事的寓意似乎是,如果您无法通过索引查找列,请确保您提供给索引器的列名称与DataColumn的名称完全匹配.
缓存该值似乎也几乎快了两倍:
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Run Code Online (Sandbox Code Playgroud)
所以最有效的方法 …
我想避免在我的代码中进行如下的许多检查:
myObj.someStringField = rdr.IsDBNull(someOrdinal)
? string.Empty
: rdr.GetString(someOrdinal);
Run Code Online (Sandbox Code Playgroud)
我想我可以让我的查询通过执行以下操作来处理空值:
SELECT myField1, [isnull](myField1, '')
FROM myTable1
WHERE myField1 = someCondition
Run Code Online (Sandbox Code Playgroud)
我虽然使用SQLite,但似乎没有认识到这个isnull功能.我也试过其他数据库中的一些公认的那些等效(NVL(),IFNULL()和COALESCE()),但SQLite的似乎不认识任何人.
有没有人有任何建议或知道更好的方法来做到这一点.不幸的是,数据库没有所有字段的默认值.另外,LEFT JOIN在某些情况下我需要使用一些子句,其中返回的某些字段将为null,因为LEFT JOIN表中的匹配记录将不存在.
null和System.DBNull.Value之间有什么区别吗?如果是,那是什么?
我现在注意到了这种行为 -
while (rdr.Read())
{
if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value)
{
int x = Convert.ToInt32(rdr["Id"]);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然我使用sql datareader从数据库中检索数据,但是没有返回if(rdr["Id"] != null)返回的值,true并最终抛出异常以将null转换为整数.
但是,如果我使用if (rdr["Id"] != System.DBNull.Value)返回false.
null和System.DBNull.Value之间有什么区别?
我想生成从MS-Access数据库检索并存储在DataTable对象/变量myDataTable中的一些格式化数据输出.但是,myDataTable中的一些字段包含dbNull数据.因此,如果任何字段lastname,intials或sID的值为dbNull,则以下VB.net代码段将给出错误.
dim myDataTable as DataTable
dim tmpStr as String
dim sID as Integer = 1
...
myDataTable = myTableAdapter.GetData() ' Reads the data from MS-Access table
...
For Each myItem As DataRow In myDataTable.Rows
tmpStr = nameItem("lastname") + " " + nameItem("initials")
If myItem("sID")=sID Then
' Do something
End If
' print tmpStr
Next
Run Code Online (Sandbox Code Playgroud)
所以,我如何得到上面的代码工作时字段可能包含的DBNull,而不必每次数据是否为DBNull在时间来检查这个问题?
在.NET中有一个null引用,它在任何地方用来表示对象引用是空的,然后有DBNull数据库驱动程序(和其他几个)用来表示......几乎相同的东西.当然,这会产生很多混乱,转换例程必须被制作出来,等等.
那么为什么最初的.NET作者决定这样呢?对我来说没有任何意义.他们的文档也没有意义:
DBNull类表示不存在的值.例如,在数据库中,表行中的列可能不包含任何数据.也就是说,该列被认为根本不存在而不仅仅是没有值.DBNull对象表示不存在的列.此外,COM interop使用DBNull类来区分VT_NULL变量(表示不存在的值)和VT_EMPTY变量(表示未指定的值).
什么是关于"不存在的列"的废话?存在一列,它只是没有特定行的值.如果它不存在,我会尝试访问特定的单元格,而不是DBNull!我可以理解区分VT_NULL和之间的必要性VT_EMPTY,但是为什么不做一个COMEmpty类呢?这将是整个.NET框架中更适合的.
我错过了什么吗?任何人都可以解释为什么DBNull被发明以及它有助于解决的问题?
我正在尝试执行一个存储过程,然后使用if语句来检查空值,我现在做的很短.我是一个VB人,所以如果我正在制作男生语法错误,请耐心等待.
objConn = new SqlConnection(strConnection);
objConn.Open();
objCmd = new SqlCommand(strSQL, objConn);
rsData = objCmd.ExecuteReader();
rsData.Read();
if (!(rsData["usr.ursrdaystime"].Equals(System.DBNull.Value)))
{
strLevel = rsData["usr.ursrdaystime"].ToString();
}
Run Code Online (Sandbox Code Playgroud)
这是否允许我检查SQL连接是否只返回一个值,如果是,那么填充我的字符串?
我习惯于只是检查下面的内容,看看是否正在返回一个值而不确定我是否正确使用C#
如果不是IsDBNull(rsData("usr.ursrdaystime"))
任何帮助,将不胜感激!
我有一个DateTime?我正在尝试使用a插入字段DbParameter.我正在创建这样的参数:
DbParameter datePrm = updateStmt.CreateParameter();
datePrm.ParameterName = "@change_date";
Run Code Online (Sandbox Code Playgroud)
然后我想把s 的值DateTime?放到dataPrm.Valuewhile中null.
我以为我最初很聪明:
datePrm.Value = nullableDate ?? DBNull.Value;
Run Code Online (Sandbox Code Playgroud)
但是因错误而失败
接线员'??' 不能应用于'System.DateTime?'类型的操作数 和'System.DBNull'
所以我想这只有在第二个参数是第一个参数的非可空版本时才有效.那么我去了:
datePrm.Value = nullableDate.HasValue ? nullableDate.Value : DBNull.Value;
Run Code Online (Sandbox Code Playgroud)
但这也不起作用:
无法确定条件表达式的类型,因为'System.DateTime'和'System.DBNull'之间没有隐式转换
但我不想在这些类型之间进行转换!
到目前为止,我唯一可以上班的是:
if (nullableDate.HasValue)
datePrm.Value = nullableDate.Value;
else
datePrm.Value = DBNull.Value;
Run Code Online (Sandbox Code Playgroud)
这真的是我写这个的唯一方法吗?有没有办法使用三元运算符来实现单线程?
更新:我真的不明白为什么?? 版本不起作用.MSDN说:
?? ?? 如果左侧操作数不为null,则运算符返回左侧操作数,否则返回右侧操作数.
这正是我想要的!
Update2:最后有点明显:
datePrm.Value = nullableDate ?? (object)DBNull.Value;
Run Code Online (Sandbox Code Playgroud) 以下代码将无法编译:
string foo = "bar";
Object o = foo == null ? DBNull.Value : foo;
Run Code Online (Sandbox Code Playgroud)
我得到:错误1无法确定条件表达式的类型,因为'System.DBNull'和'string'之间没有隐式转换
要解决这个问题,我必须做这样的事情:
string foo = "bar";
Object o = foo == null ? DBNull.Value : (Object)foo;
Run Code Online (Sandbox Code Playgroud)
这个演员似乎毫无意义,因为这肯定是合法的:
string foo = "bar";
Object o = foo == null ? "gork" : foo;
Run Code Online (Sandbox Code Playgroud)
在我看来,当三元分支具有不同类型时,编译器不会将值自动提供给类型对象...但是当它们属于相同类型时,则自动装箱是自动的.
在我看来,第一个声明应该是合法的......
任何人都可以描述为什么编译器不允许这样做以及为什么C#的设计者选择这样做?我相信这在Java中是合法的......虽然我没有验证这一点.
谢谢.
编辑:我要求理解为什么Java和C#以不同的方式处理这个问题,C#中的场景下发生了什么使得它无效.我知道如何使用三元,而不是寻找一个"更好的方法"来编写示例代码.我理解C#中的三元规则,但我想知道为什么......
编辑(Jon Skeet):删除了"autoboxing"标签,因为这个问题没有涉及拳击.
有没有更好/更清洁的方法来做到这一点?
int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
stockvalue = (int)reader["StockValue"];
Run Code Online (Sandbox Code Playgroud)