I have a strange issue where a piece of code that I run all the time is suddenly throwing a "System.NullReferenceException: Object reference not set to an instance of an object." error.
The error occurs on a line involving a custom class that I made to simplify running TSQL action queries with parameters. With the class, I just have to use the naming convention @Param0, @Param1, etc, and pass an array of this type:
public struct SQLParam
{
private SqlDbType m_Type;
private dynamic m_Value;
public SqlDbType Type
{
get { return m_Type; }
set { m_Type = value; }
}
public dynamic Value
{
get { return m_Value; }
set { m_Value = value; }
}
public SQLParam (SqlDbType ValType, dynamic val)
{
m_Value = val;
m_Type = ValType;
}
public SQLParam(SqlParameter sqlParameter)
{
m_Value = sqlParameter.Value;
m_Type = sqlParameter.SqlDbType;
}
}
...into a method of an object of the class GCDB, called "ActionQueryWithParams", and it works. Except this one time.
Here's the code that's having trouble. I'm including various examples of code that DOES work, and marking the code that DOESN'T in comments:
GCDB GeekConn = new GCDB();
string sID = "";
string sRecurrenceID = JobRecurrenceID.Text.ToString();
if (string.IsNullOrEmpty(JobID.Text.ToString())) //added record
{
//insert job --- THIS WORKS
SQLParam[] paramslist = new SQLParam[6];
string sSQL = "INSERT INTO [dbo].[Jobs] ([CustomerID], [JobName], [JobDescription], [IsRecurringJob], [JobStatusID], [LastModifiedByStaffID]) " +
"OUTPUT INSERTED.JobID " +
"VALUES(@Param0, @Param1, @Param2, @Param3, @Param4, @Param5)";
paramslist[0] = new SQLParam(SqlDbType.Int, Convert.ToInt32(cboCustomerID.SelectedValue));
paramslist[1] = new SQLParam(SqlDbType.VarChar, JobName.Text);
paramslist[2] = new SQLParam(SqlDbType.VarChar, JobDescription.Text);
paramslist[3] = new SQLParam(SqlDbType.Bit, Convert.ToBoolean(IsRecurringJob.Checked));
paramslist[4] = new SQLParam(SqlDbType.Int, Convert.ToInt32(cboJobStatusID.SelectedValue));
paramslist[5] = new SQLParam(SqlDbType.Int, System.Web.HttpContext.Current.Session["StaffID"]);
GeekConn.ActionQueryWithParams(sSQL, paramslist);
if (GeekConn.InsertedID != null)
{
sID = GeekConn.InsertedID.ToString();
}
paramslist = null;
//insert new assignment (if applicable - if adding a job to a staff person's list) -- THIS WORKS
if (!string.IsNullOrEmpty(AssignedToStaffID.Text.ToString()))
{
paramslist = new SQLParam[2];
sSQL = "INSERT INTO [dbo].[JobAssignments] ([JobID], [StaffID]) " +
"SELECT @Param0 AS JobID, @Param1 AS StaffID " +
"WHERE NOT EXISTS(SELECT * FROM[dbo].[JobAssignments] WHERE JobID = @Param0 AND StaffID = @Param1)";
paramslist[0] = new SQLParam(SqlDbType.Int, Convert.ToInt32(sID));
paramslist[1] = new SQLParam(SqlDbType.Int, Convert.ToInt32(AssignedToStaffID.Text.ToString()));
GeekConn.ActionQueryWithParams(sSQL, paramslist);
}
paramslist = null;
}
else //edited record
{
//do the main update -- THIS WORKS
SQLParam[] paramslist = new SQLParam[7];
string sSQL = "UPDATE[dbo].[Jobs] " +
"SET [CustomerID] = @Param0 " +
",[JobName] = @Param1 " +
",[JobDescription] = @Param2 " +
",[IsRecurringJob] = @Param3 " +
",[JobStatusID] = @Param4 " +
",[LastModifiedByStaffID] = @Param5 " +
",[DateModified] = getdate() " +
"WHERE [JobID] = @Param6";
paramslist[0] = new SQLParam(SqlDbType.Int, Convert.ToInt32(cboCustomerID.SelectedValue));
paramslist[1] = new SQLParam(SqlDbType.VarChar, JobName.Text);
paramslist[2] = new SQLParam(SqlDbType.VarChar, JobDescription.Text);
paramslist[3] = new SQLParam(SqlDbType.Bit, Convert.ToBoolean(IsRecurringJob.Checked));
paramslist[4] = new SQLParam(SqlDbType.Int, Convert.ToInt32(cboJobStatusID.SelectedValue));
paramslist[5] = new SQLParam(SqlDbType.Int, System.Web.HttpContext.Current.Session["StaffID"]);
paramslist[6] = new SQLParam(SqlDbType.Int, Convert.ToInt32(JobID.Text));
GeekConn.ActionQueryWithParams(sSQL, paramslist);
paramslist = null;
//auto insert new occurrence (if this is a recurring job and there are no occurrences already) -- THIS THROWS AN ERROR
if ((IsRecurringJob.Checked) && (JobRecurrenceID.Text.ToString() == ""))
{
paramslist = new SQLParam[2];
sSQL = "INSERT INTO [dbo].[JobRecurrences] ([JobID], [StatusLastModified], [LastModifiedByStaffID]) " +
"OUTPUT INSERTED.[JobRecurrenceID] " +
"SELECT @Param0 AS JobID, getdate(), @Param1 AS StaffID " +
"WHERE NOT EXISTS (SELECT * FROM [dbo].[JobRecurrences] WHERE JobID = @Param0)";
paramslist[0] = new SQLParam(SqlDbType.Int, Convert.ToInt32(JobID.Text));
paramslist[1] = new SQLParam(SqlDbType.Int, System.Web.HttpContext.Current.Session["StaffID"]);
// ERROR IS HERE: System.NullReferenceException: Object reference not set to an instance of an object.
GeekConn.ActionQueryWithParams(sSQL, paramslist);
if (GeekConn.InsertedID != null)
{
sRecurrenceID = GeekConn.InsertedID.ToString();
}
}
paramslist = null;
}
GeekConn = null;
I've confirmed that the SQL statement for auto-inserting a new occurrence works in SSMS. And, as far as I can tell, there's nothing in the broken code that isn't also in the working code. Can anybody spot anything I'm missing?
Many thanks!