为什么编译器在将System.Object设置为False

时间:2017-08-02 14:12:50

标签: c# .net vb.net generics

我写了一个通用方法来从数据库中检索单个值(MSSQL Server)。
我遇到了一个需要从DB获取Boolean值的情况。

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

当DB中的值为False GenericScalar()时,方法返回False(应该如此) 并且条件:if (IsExist == null)中的GetWanLineDisconnectionData()为真且返回块正在执行,即使IsExist为False且不为null。

为什么?

我该如何克服这个问题?

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. 在开头IsExist没什么(null)。 enter image description here
  2. 查询找到一行,bool列WanLineDiscconection的值为false,IsExist设置为false。 enter image description here

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

2 个答案:

答案 0 :(得分:1)

foo中的变量object foo = false绝对不是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注入。话虽如此,在该方法中出现了更多错误,包括但不限于不处理数据库连接并在没有堆栈跟踪的情况下重新抛出异常。

答案 1 :(得分:0)

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

简而言之,这意味着T实际上是object,而不是您对数据库的期望。正如CodeCaster已经提到的那样,object的默认值只是null

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