I've had an asp.net website running live on our intranet for a couple of weeks now. I just got an email from my application_error emailer method with an unhandled exception.
Here it is (I've cleaned up some of the paths to make it better displayed)
Exception : Object reference not set to an instance of an object. Stack Trace : at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at TimesheetDomain.DataMappers.StaffMemberData.ReadStaff(SqlDataReader reader) in TimesheetDomain\DataMappers\StaffMemberData.cs:line 362
at TimesheetDomain.DataMappers.StaffMemberData.GetStaffMember(String name) in TimesheetDomain\DataMappers\StaffMemberData.cs:line 401
at TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName(String name) in TimesheetDomain\ServiceLayer\TimesheetManager.cs:line 199
at UserVerification.GetCurrentUser() in \App_Code\UserVerification.cs:line 29 at WebTimesheets.OnInit(EventArgs e) in \WebTimesheets\WebTimesheets.master.cs:line 159
at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Basically it looks like it's erroring at my ReadStaff method which reads a data reader to build staff member objects. Here is the bit of code:
while (reader != null && reader.Read()) { StaffMember newMember = null; string firstName = reader["FirstName"].ToString(); string lastName = reader["LastName"].ToString(); int staffID = (int)reader["StaffID"]; int employSection = (int)reader["EmploySection"]; StaffType employType = (StaffType)employSection; string emailAddress = reader["EmailInt"].ToString(); int employCode = (int)reader["ibbwid"]; //check if they are an admin staff member if (IsAdminStaff(employType)) { newMember = new AdminOfficer(firstName, lastName, employType, staffID, emailAddress, employCode); } else { //check if they are a supervisor if (IsASupervisor(staffID)) newMember = new Supervisor(firstName, lastName, employType, staffID, emailAddress, employCode); else newMember = new StaffMember(firstName, lastName, employType, staffID, emailAddress, employCode); } //add to identity map if (!_staffMembers.ContainsKey(staffID)) _staffMembers.Add(staffID, newMember); //****THIS IS LINE 362***** else _staffMembers[staffID] = newMember; }
(Line 362 is 3rd last line) I'm using an identity map (just read fowlers book on patterns and thought it was a good idea - may have done it wrong, happy for comments) but that's not overly relevant as later on I use the newMember
object elsewhere so if I remove that block the NullReferenceException
will occur.
I am struggling to see how on earth newMember
is null in the 3rd last line there (which is the line that errored).
Resharper/VS doesn't give me a warning that it could be null
- because there's the 3 constructors which I choose from.
Can anyone suggest where I can look to try and fix this error? It's only happened once and that method has been called thousands of times since the site went live.
Thanks
[EDIT] As Requested, here's the IComparer for staff member
/// <summary> /// Comparer for staff members - compares on name /// </summary> public class StaffMemberComparer : IComparer { public int Compare(object x, object y) { //check they are staff members if (x is StaffMember && y is StaffMember) { //do a simple string comparison on names StaffMember staffX = x as StaffMember; StaffMember staffY = y as StaffMember; return String.Compare(staffX.FirstName, staffY.FirstName); } throw new Exception("This is for comparing Staff Members"); } }
and it's used in the IComparable implementation
/// <summary> /// IComparable implementaiton /// </summary> /// <param name="obj">object to compare to</param> /// <returns></returns> public int CompareTo(object obj) { StaffMemberComparer comparer = new StaffMemberComparer(); return comparer.Compare(this, obj); }
So, a reference is what a variable of a reference type contains. These variables can point to “nothing”, though, and that's what we call a null reference: a reference that doesn't point to any object. When you try to call a method or another member on the said variable, you got the NullReferenceException.
You can eliminate the exception by declaring the number of elements in the array before initializing it, as the following example does. For more information on declaring and initializing arrays, see Arrays and Arrays. You get a null return value from a method, and then call a method on the returned type.
The best way to avoid the "NullReferenceException: Object reference not set to an instance of an object” error is to check the values of all variables while coding. You can also use a simple if-else statement to check for null values, such as if (numbers!= null) to avoid this exception.
It is almost certainly a threading issue - see this question and its accepted answer.
Dictionary<>.Insert()
will throw a NullReferenceException
internally if the dictionary instance is modified from another thread during the insert operation.
As of .NET 4.0 you can use ConcurrentDictionary and avoid the threading issues associated with manipulating the same dictionary from multiple threads simultaneously.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With