2017-08-02 67 views
0

我编写了一个通用方法来从数据库(MSSQL Server)中检索单个值。
我遇到了一个案例,我需要从数据库中获取Boolean值。为什么编译器将它设置为False时将System.Object视为null为什么编译器将它设置为False

正如您在下面的代码中看到的,Object本地字段(IsExist)会得到结果。

当DB值为False GenericScalar()方法返回False(因为它应该) 和条件:if (IsExist == null)GetWanLineDisconnectionData()的真实,返回块被执行,即使是ISEXIST虚假和不为空。

这是为什么?

我该如何克服这个问题?

private void GetWanLineDisconnectionData() 
{ 
    string q = "SELECT WanLineDiscconection FROM AdditionalProjectsData WHERE SpCall= " + "'" + spCall + "'"; 
    object IsExist = Orange.ProjectManagment.DAL.Database.GenericScalar<object>(q); 
    if (IsExist == null) { 
     return; 
    } 
    if (bool.Parse(IsExist) == true) { 
     RadWanDiscYes.Checked = true; 
    } else { 
     RadWanDiscNo.Checked = true; 
    }  
} 

数据库的方法:

public static T GenericScalar<T>(string query) 
{ 
    OleDbConnection connection = new OleDbConnection(sqlConnString); 
    connection.Open(); 

    OleDbCommand cmd = new OleDbCommand(query, connection); 
    try 
    { 
     var result = cmd.ExecuteScalar(); 

     if (result == null) 
     { 
      return default(T); 
     } 
     else 
     { 
      return (T)result; 
     } 
    } 

    catch (Exception ex) 
    { 
     throw ex; 
    } 
    finally 
    { 
     CloseConnection(ref connection); 
    } 
} 

编辑:
也许几个屏幕芽将更好地展示它: (注意:GetWanLineDisconnectionData()是写在VB.NET和GenericScalar()写在C#在解决方案中的另一个项目中):

  1. in beginn ing IsExist是空(null)。 enter image description here
  2. 该查询找到一行,并且bool列WanLineDiscconection的值为false,并且IsExist设置为false,因为它应该是。 enter image description here

  3. 这里是问题所在,程序进入if区块并且IsExist不是空(null)。 enter image description here

+1

它的空值为无值,但DBNull.Value为数据库空的btw。 –

+1

请使用'使用'块,您的片段是一个教材如何通过尝试自己做它搞砸了样本。不要'抛出;'。只能使用'throw;',另一种方法会扰乱堆栈跟踪。 – nvoigt

+0

“WanLineDiscconection”的类型是什么? – HimBromBeere

回答

1

object foo = false变量foo绝对不是null,所以在您的标题前提是不正确。

ExecuteScalar()返回null当没有行时。在这种情况下,方法GenericScalar()返回default(T),这对于object将是null

如何解决这个问题取决于你的数据是什么样的。你可能想表示一个可空INT的结果,或int?代替object

var exists = Orange.ProjectManagment.DAL.Database.GenericScalar<int?>(q); 
RadWanDiscYes.Checked = exists.GetValueOrDefault() > 0; 

How does GetValueOrDefault work?What is the default value of the nullable type "int?" (including question mark)?。除此之外:你通常也不想在数据库查询中编写方便的包装器,因为你重新发明了轮子,打开了SQL注入的应用程序。这就是说,这种方法出现了很多问题,包括但不限于不处理数据库连接,并在没有堆栈跟踪的情况下重新抛出异常。

+0

为什么不使用'exists.HasValue'?似乎比查询价值和确定这个价值是否大于零更容易,不是吗? – HimBromBeere

+0

@HimBromBeere正如答案中所述,我不知道他们的数据是什么样子。 '(int?)0'有一个值,但可能意味着'false'。 – CodeCaster

+0

@CodeCaster感谢您的回复和代码审查笔记,但是有一行,并且布尔列WanLineDiscconection的值为false,因此“IsExist”值为false(非null),它是在查询中,问题出现在GetWanLineDisconnectionData()方法中:条件'(IsExist == null)'将其视为null并且不像它应该是false并且if块被执行(并且它不应该被执行) ,我知道这听起来很奇怪,我测试了几次,我不明白为什么。 – jonathana

0

你是混合编译时间和运行时间信息。虽然GenericScalar<object>(q)是在编译时存在的信息,从ExecuteScalar编译返回的类型时间只是object。您希望它是boolean,对于您的特定情况可能会也可能不会。但是这与编译器无关。

简而言之,这意味着T实际上是object,而不是您期望它来自数据库的任何内容。正如CodeCaster所提到的,object的默认值只是null

Si我建议使用GenericScalar<bool>而不是GenericScalar<object>,因为您似乎知道您的查询实际返回的结果 - 在您的情况下为bool。然后default(T)评估为false,而不是null

+0

谢谢你的回应,我已经用bool类型尝试过了。请参阅我对CodeCaster答案的评论。 – jonathana

+0

请查看我对这个问题的编辑 – jonathana

相关问题