【问题标题】:NullReferenceException but there are no nullNullReferenceException 但没有 null
【发布时间】:2017-06-02 06:33:44
【问题描述】:

我在下面的这一行给出了我标题上的错误。

dtDetail = SQLQuery.getRequestDetails(reqNo, vendorcode);

但我测试了,dtDetail 不为空,reqNo 不为空,vendorCode 不为空,我不知道。

logger.Debug("request#: " + reqNo);
logger.Debug("vendor code: " + vendorcode);
System.Data.DataTable dtDetail = new System.Data.DataTable();
if (dtDetail == null)
    logger.Debug("dtDetail is null.");
if (SQLQuery.getRequestDetails(reqNo, vendorcode) == null)
    logger.Debug("SQLQuery.getRequestDetails(reqNo, vendorcode) is null.");
dtDetail = SQLQuery.getRequestDetails(reqNo, vendorcode);

我使用从logger.Debug 得到的reqNovendorCode 测试了SQLQuery.getRequestDetails(reqNo, vendorcode),那里没有异常。

所有测试都在我的本地 PC 上完成,但连接到生产数据库。 Windows 7 专业版服务包 1。

给我错误的是生产环境,Windows XP Pro 2002 Service Pack 3。

下面是 SQLQuery 类。

public static class SQLQuery
{
    private static ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    public static DataTable getRequestDetails(string reqNo, string vendorcode)
    {
        DataSet ds = new DataSet();
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT * FROM vw_drawing_req_status WHERE  regno = '" + reqNo + "'" + " AND vendorcode = '" + vendorcode + "'";

            ds = myDB.GetDataSet(strSQL);
        }
        catch (Exception ex)
        {
            logger.Error("request#: " + reqNo + ", vendor code: " + vendorcode, ex);
            throw ex;
        }
        finally
        {

        }
        if (ds.Tables[0].Rows.Count > 0)
            return ds.Tables[0];
        else
            return null;
    }

    public static DataTable getRFQDetail(string reqNo, string vendorcode)
    {
        DataSet ds;
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT * FROM t_RFQ_info WHERE  regno = '" + reqNo + "'" +
                "AND vendor_code = '" + vendorcode + "'";

            ds = myDB.GetDataSet(strSQL);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
        if (ds.Tables[0].Rows.Count > 0)
            return ds.Tables[0];
        else
            return null;
    }

    public static DataTable getVendorEmailAddress(string comp_code, string vendorcode)
    {
        DataSet ds;
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT * FROM t_vendor_email WHERE  comp_code = '" + comp_code + "'" +
                "AND vendor = '" + vendorcode + "' AND status = 1";

            ds = myDB.GetDataSet(strSQL);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }

        return ds.Tables[0];

    }

    public static string getModuleNumber(string reqNo)
    {
        DataSet ds;
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT moduleno FROM subconjobQ WHERE  regno = '" + reqNo + "'";

            ret = myDB.GetOneValue(strSQL).ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
        return ret;
    }

    public static string getPlant(string reqNo)
    {
        DataSet ds;
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT plant FROM subconjobQ WHERE  regno = '" + reqNo + "'";

            ret = myDB.GetOneValue(strSQL).ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
        return ret;
    }

    public static string getVendorCurrency(string plant, string vendorcode)
    {
        DataSet ds;
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " SELECT currency FROM t_vendor_info WHERE  plant = '" + plant + "'" +
                "AND vendor = '" + vendorcode + "' AND status = 1";

            ret = myDB.GetOneValue(strSQL).ToString();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
        return ret;
    }

    public static void updateRFQTable(string regno, string vendor, string partno, string currency, double procCost, double rawCost, double treatCost, double unitPrice, string leadTime)
    {
        string strSQL = string.Empty;
        ATSSPCommon.SQLDB myDB = null;
        string ret = string.Empty;
        try
        {
            string strConnectionString = Config.DrawingConnString();
            myDB = new ATSSPCommon.SQLDB(strConnectionString);

            strSQL = " UPDATE t_RFQ_info SET " +
                "currency = '" + currency + "', " +
                "process_cost = " + procCost + ", " +
                "rawmat_cost = " + rawCost + ", " +
                "treatment_cost = " + treatCost + ", " +
                "unit_price = " + unitPrice + ", " +
                "lead_time = '" + leadTime.Trim() + "', " +
                "status = 1 " +
                "WHERE Regno = '" + regno + "' AND " +
                "vendor_code = '" + vendor + "' AND " +
                "partno = '" + partno + "'";

            myDB.ExecuteSQL(strSQL);
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
    }
}

我什至去写了一个新函数,但它在生产环境中也给了我同样的错误。

class RFQHandler
{
    public static DataTable GetRequestDetail(string requestNumber, string vendorCode)
    {
        string connectionString = Config.DrawingConnString();
        SqlConnection sqlConnection = new SqlConnection(connectionString);
        string commandText = "SELECT * FROM vw_drawing_req_status WHERE regno = @requestNumber AND vendorcode = @vendorCode";
        SqlCommand sqlCommand = new SqlCommand(commandText, sqlConnection);
        sqlCommand.Parameters.Add("@requestNumber", SqlDbType.Char, 12).Value = requestNumber;
        sqlCommand.Parameters.Add("@vendorCode", SqlDbType.VarChar, 25).Value = vendorCode;
        DataTable requestDetail = new DataTable();
        using (sqlConnection)
        using (sqlCommand)
        {
            sqlConnection.Open();
            using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
            {
                requestDetail.Load(sqlDataReader);
            }
        }
        return requestDetail;
    }
}

记录的错误消息:

2017-01-18 15:30:53,303 [1] 错误 DrawingRequestEmail.Util [(null)] - ReceiveEmail System.NullReferenceException:对象引用未设置为对象的实例。 在 D:\TFS\SERVER\Logistics\Main\MM\DrawingRequest\DrawingRequestEmail\DrawingRequestEmail\Email.cs:line 155 中的 DrawingRequestEmail.Email.ProcessEmailFromSubconSystem(MailItem 消息) 在 D:\TFS\SERVER\Logistics\Main\MM\DrawingRequest\DrawingRequestEmail\DrawingRequestEmail\Util.cs:line 123 中的 DrawingRequestEmail.Util.ReceiveEmail() 处

Util.cs:第 123 行

ret = email.ProcessEmailFromSubconSystem(oMessage);

Email.cs:第 155 行

dtDetail = SQLQuery.getRequestDetails(reqNo, vendorcode);

【问题讨论】:

  • 能否请您删除不相关的代码,并仅包含引发异常的块
  • @GrantWinney 我测试了getRequestDetails,没有错误。
  • 您的问题缺少信息;它在哪个环境中返回 NullReferenceException?提供两种环境的详细信息,一种会产生错误,另一种不会产生错误。
  • 在您编写的新函数中,您能否准确检查在哪一行引发了异常?您能否提供异常的详细信息?
  • @EmersonCardoso 我无法在生产环境中设置断点。我在编辑中更新了异常。

标签: c# console-application windows-xp .net-2.0


【解决方案1】:

一个可能的空引用错误,我可以看到是这个-

    DataSet ds = new DataSet();
    string strSQL = string.Empty;
    ATSSPCommon.SQLDB myDB = null;
    string ret = string.Empty;
    try
    {
        ........
        ds = myDB.GetDataSet(strSQL);
    }
    catch (Exception ex)
    {
        ....
    }
    finally
    {

    }
    if (ds.Tables[0].Rows.Count > 0) // this could be the error
        return ds.Tables[0];
    else
        return null;

即使查询执行,也不能保证在DataSet 中至少有一个DataTable,而且DataSet 本身也可能为空。尝试像这样添加一个空检查 -

if (ds != null && ds.Tables.Any() && ds.Tables[0].Rows.Count > 0) 
        return ds.Tables[0];
    else
        return null;

在此语句之后也没有空检查 -

myDB = new ATSSPCommon.SQLDB(strConnectionString);

myDB 也可以为空。

更新:对于 .net 2.0,请尝试 ds.Tables.Count > 0 而不是评论中提到的 ds.Tables.Any()

【讨论】:

  • 我删除了检查,只剩下return ds.Tables[0];,它仍然给我错误。
  • 那还需要检查。你怎么知道肯定有桌子? Table[0] 表示它在索引 0 处有一个表。
  • 在我的测试中(指向生产数据库),我已经确保我的查询会返回一些东西。即使我没有myDB 的新GetRequestDetail 和检查也给了我同样的错误。
  • .Net 2.0,我不能使用ds.Tables.Any()
  • 我用if (ds != null && ds.Tables[0].Rows.Count > 0)测试过,还是报错。
【解决方案2】:

我也遇到了一个无意义的 NULL 异常,我将其追溯到一个变量声明,当我使用“设置下一条语句”(Ctrl+Shift+F10) 时,调试器跳过了它。

例如,我的代码如下所示:

if (false)
{
    classTypeObject myObject;
    myObject = someValue;
}

如果我在条件上设置断点,然后移动下一条语句以在左大括号上运行,当设置 myObject 的值时,我会收到空​​引用异常,因为调试器必须跳过声明。

但是,如果我将代码更改为这样并执行相同的调试步骤,则没有问题:

classTypeObject myObject;
if (false)
{
    myObject = someValue;
}

附:显然这是伪代码,你永远不想硬编码if (false)

【讨论】:

    猜你喜欢
    • 2017-06-16
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 2012-08-22
    • 2021-04-20
    • 1970-01-01
    • 2022-11-06
    • 2016-01-28
    相关资源
    最近更新 更多