我是如何在构造函数之后立即得到此NullReferenceException错误的?

时间:2009-08-24 02:41:09

标签: c# asp.net nullreferenceexception

我已经在我们的内联网上运行了几个星期的asp.net网站。我收到了来自我的application_error电子邮件发送方法的电子邮件,其中包含未处理的异常。

这是(我已经清理了一些路径以使其更好地显示)

  

异常:对象引用未设置为对象的实例。   Stack Trace:在System.Collections.Generic.Dictionary`2.Insert(TKey键,TValue值,布尔加法)处于System.Collections.Generic.Dictionary`2.Add(TKey键,TValue值)    在TimesheetDomain \ DataMappers \ StaffMemberData.cs中的TimesheetDomain.DataMappers.StaffMemberData.ReadStaff(SqlDataReader reader):第362行

     

在   TimesheetDomain.DataMappers.StaffMemberData.GetStaffMember(字符串   姓名)in   TimesheetDomain \ DataMappers \ StaffMemberData.cs:行   401

     

在   TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName(字符串   姓名)in   TimesheetDomain \ ServiceLayer \ TimesheetManager.cs:行   199

     

在UserVerification.GetCurrentUser()   在\ App_Code \ UserVerification.cs:行   29在WebTimesheets.OnInit(EventArgs   e)in   \ WebTimesheets \ WebTimesheets.master.cs:行   159

     

在   System.Web.UI.Control.InitRecursive(控制   namingContainer)at   System.Web.UI.Control.InitRecursive(控制   namingContainer)at   System.Web.UI.Page.ProcessRequestMain(布尔   includeStagesBeforeAsyncPoint,Boolean   includeStagesAfterAsyncPoint)

基本上,我的ReadStaff方法看起来错误,它读取数据读取器来构建人员成员对象。这是一些代码:

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;
}

(362行是最后一行) 我正在使用身份地图(只是阅读有关模式的fowlers书,并认为这是一个好主意 - 可能做错了,对评论感到高兴)但这并不过分相关,因为后来我在其他地方使用newMember对象因此,如果我删除该块,则会发生NullReferenceException

我很难看到地球上的第3个最后一行newMember是否为空(这是错误的行)。

Resharper / VS没有给我一个警告,它可能是null - 因为我选择了3个构造函数。

任何人都可以建议我可以尝试修复此错误吗?它只发生过一次,自该网站上线以来,该方法已被召集数千次。

由于

[编辑] 如所要求的,这是工作人员的IComparer

/// <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");
    }
}

它在IComparable实现中使用

/// <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);
}

6 个答案:

答案 0 :(得分:112)

这几乎肯定是一个线程问题 - 请参阅this question and its accepted answer

如果在插入操作期间从另一个线程修改了字典实例,

Dictionary<>.Insert()将在内部抛出NullReferenceException

答案 1 :(得分:16)

从.NET 4.0开始,您可以使用ConcurrentDictionary并避免与同时从多个线程操作相同字典相关的线程问题。

答案 2 :(得分:1)

我看不出任何明显的东西。我运行一些SQL来检查数据库是否有任何不良数据。问题可能是相关输入表单中的怪异错误。如果代码已经运行了数千次而没有发生任何事故,那么我将围绕有问题的代码块包含一些额外的异常处理/报告,这样你至少可以在下次发生时获得一个staffId。

你可能会在这样的事情上浪费很多时间。最有效的方法可能只是让它在上述/受控条件下再次失败.....假设它造成的破坏程度是可接受的/可管理的/次要的。

我很欣赏它不会满足迫切需要知道,但它可能是管理问题的最佳方式,尤其是在故障率较低的情况下。

答案 3 :(得分:1)

  

这只发生过一次   方法已经被称为数千个   自该网站上线以来的时间。

阅读完之后,我可以得出结论,.NET可能已经耗尽了内存并且无法创建更多的Dictionary键,它可能并不是你的错。但是,当我们尝试在会话/应用程序变量中存储过多信息时,我们确实遇到了这类错误,从而增加了Web应用程序的内存占用。但是当我们的数字非常高时,我们会遇到这样的错误,例如在词典或列表等中存储10,000个项目。

模式很好,但你必须意识到我们使用数据库以关系格式存储信息,如果我们开始使用内存来存储类似的东西,那么我们忽略了强大的数据库。数据库也可以为您缓存值。

这可能听起来很傻但我们的Windows服务器每24小时重启一次,午夜时没有流量。这确实帮助我们摆脱了这些错误。我们定期按照修复计划重新启动服务器,以便清除所有缓存/日志。

答案 4 :(得分:0)

正如其他人所说,比较可能导致问题 是否有任何比较标准包含空值?特别是字符串属性?

即。如果firstname或lastname或emailId为null,并且如果在比较中使用它,则在字典中使用时可能会失败以进行比较。

编辑:主管和职员与AdminStaff课程有何关联? 在代码中,您将两个实例都转换为StaffMember。我的猜测是,如果Supervisor和StaffMember类相关,则可能会出现问题。

EDIT2:字典实例的scrope是什么?它是在应用程序级别/会话级别共享的吗?多个线程是否可能尝试从中读取/写入?

答案 5 :(得分:0)

我看到这个与线程无关的异常的另一种方法是序列化Dictionary。在这种情况下,它是空的,但我仍然在反序列化实例的Insert()方法中得到NullReferenceException。

我的案例中的简单更改只是在反序列化后创建一个新实例。我不确定序列化是否会破坏字典,或者它是否是为字典定义的类型。

在我的情况下,没有序列化代理的类型是不可序列化的(我提供了这些),但是字典中的某些东西在这里有问题。但是,字典仍然是空的,这仍然发生。