Jak uzyskałem ten błąd NullReferenceException zaraz po konstruktorze?

I ' ve had an asp.net strona działa na żywo w naszym Intranecie już od kilku tygodni. Właśnie dostałem wiadomość e-mail z mojej metody application_error emailer z nieobsługiwanym wyjątkiem.

Oto jest (wyczyściłem kilka ścieżek, aby było lepiej wyświetlane)

Wyjątek: odniesienie do obiektu nie jest ustawione na instancję obiektu. Stack Trace: system at.Kolekcje.Ogólne.Słownik " 2.Insert (klucz TKey, wartość TValue, Boolean add) at System.Kolekcje.Ogólne.Słownik " 2.Add (klucz TKey, wartość TValue) / align = "left" / DataMappers.Dane personalne.ReadStaff (SqlDataReader reader) w TimesheetDomain\DataMappers\StaffMemberData.cs: line 362

At TimesheetDomain.DataMappers.Dane personalne.GetStaffMember(String nazwa) w TimesheetDomain \ DataMappers\StaffMemberData.cs: line 401

At TimesheetDomain.Serwisant.TimesheetManager.GetUserFromName(String nazwa) w TimesheetDomain\ServiceLayer\TimesheetManager.cs: line 199

W UserVerification.GetCurrentUser() w \App_Code\UserVerification.cs: line 29 w WebTimesheets.OnInit(EventArgs e) w \WebTimesheets\WebTimesheets.Mistrzu.cs: line 159

At System.Www.UI.Kontrola.InitRecursive(Kontrola namingContainer) w System.Www.UI.Kontrola.InitRecursive(Kontrola namingContainer) w System.Www.UI.Strona.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

W zasadzie wygląda to na błąd w mojej metodzie ReadStaff, która odczytuje czytnik danych w celu zbudowania obiektów pracownika. Oto fragment kodu:

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

(linia 362 to 3. Ostatnia linia) Używam mapy tożsamości (po prostu przeczytałem książkę o szablonach i pomyślałem, że to dobry pomysł - może źle zrobiłem, cieszę się na komentarze) ale to nie jest zbyt istotne, ponieważ później używam obiektu newMember gdzie indziej, więc jeśli usunę ten blok NullReferenceException będzie występuje.

Walczę, aby zobaczyć, jak na ziemi newMember jest null w trzeciej ostatniej linii (która jest linią, która się pomyliła).

Resharper / VS nie ostrzega mnie, że to może być null - ponieważ są 3 konstruktory, które wybieram.

Czy ktoś może zasugerować, Gdzie mogę szukać, aby spróbować naprawić ten błąd? Zdarzyło się to tylko raz, a ta metoda została wywołana tysiące razy, odkąd strona została uruchomiona.

Dzięki

[edytuj] Zgodnie z życzeniem, oto 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");
    }
}

I jest używany w implementacji 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);
}
Author: Thomas Flinkow, 2009-08-24

6 answers

Jest to prawie na pewno problem wątkowy-Zobacz to pytanie i jego akceptowaną odpowiedź .

Dictionary<>.Insert() wyrzuci NullReferenceException wewnętrznie, jeśli instancja słownika zostanie zmodyfikowana z innego wątku podczas operacji wstawiania.

 101
Author: McKenzieG1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:49

Od wersji. NET 4.0 możesz używać współbieżności i unikać problemów związanych z przetwarzaniem tego samego słownika z wielu wątków jednocześnie.

 15
Author: Bill Noto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-17 16:44:48

Nie widzę nic oczywistego. Uruchomiłbym jakiś SQL, aby sprawdzić bazę danych pod kątem złych danych. Problemem może być dziwny błąd w powiązanej formie wejściowej. Jeśli kod był uruchamiany tysiące razy bez incydentów do tej pory, owinąłbym trochę dodatkowej obsługi/raportowania WYJĄTKÓW wokół danego bloku kodu, abyś mógł przynajmniej uzyskać staffId, jeśli / kiedy to nastąpi.

Można spalić dużo czasu na coś takiego. Najbardziej celowym podejściem może być po prostu pozwolić mu ponownie zawieść pod powyższe / kontrolowane warunki..... zakładając, że poziom zakłóceń, które powoduje, jest akceptowalny/możliwy do opanowania / niewielki.

Doceniam, że wont zaspokoić natychmiastową potrzebę wiedzieć, ale może to być najlepszy sposób, aby poradzić sobie z problemem, zwłaszcza przy tak niskiej awaryjności.

 1
Author: rism,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-24 09:28:58

To zdarzyło się tylko raz i że metoda została nazwana tysiącami czasy, od kiedy strona została uruchomiona.

Po przeczytaniu tego, mogę wywnioskować, że możliwe, że. NET może wyczerpać swoją pamięć i nie może stworzyć więcej klucza słownikowego, to może nie być nigdzie twoja wina. Ale tak, otrzymaliśmy tego rodzaju błędy, gdy staraliśmy się przechowywać zbyt dużo informacji w zmiennych sesji / aplikacji, zwiększając tym samym ślad pamięci aplikacji internetowej. Ale mieliśmy takie błędy, gdy nasze liczby poszły naprawdę wysoko, jak przechowywanie 10 000 pozycji w słowniku lub liście itp.

Wzór jest dobry, ale musisz również zdać sobie sprawę, że używamy bazy danych do przechowywania informacji w formacie relacyjnym, jeśli zaczniemy używać pamięci do przechowywania podobnych rzeczy, to ignorujemy potężną bazę danych. Baza danych może również buforować wartości dla Ciebie.

Może to zabrzmieć głupio, ale nasz windows server restartuje się co 24 godziny, o północy, gdy nie ma ruchu. Że pomógł nam w pozbyciu się takich błędów. Regularnie restartujemy nasze serwery zgodnie z harmonogramem napraw, aby wyczyścić całą pamięć podręczną/logi.

 1
Author: Akash Kava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-24 09:46:21

Jak powiedzieli inni, porównanie może być przyczyną problemu.
Czy którekolwiek z kryteriów porównania zawiera wartość null? konkretnie, właściwości łańcuchów?

Tzn. jeśli firstname lub lastname lub emailId jest null i jeśli jest używane w porównaniu, rzeczy mogą się nie udać, gdy zostaną użyte w słowniku do porównania.

EDIT: jak są powiązane z klasą Supervisor i StaffMember i AdminStaff?
W kodzie obie instancje są wysyłane do StaffMember. Zgaduję, że że może to być problem, jeśli przełożony i Pracownik klasy są nie powiązane.

EDIT2: jaki jest zakres wystąpienia słownika? Czy jest współdzielony na poziomie aplikacji/sesji? Czy to możliwe, że wiele wątków może próbować z niego odczytać/zapisać?

 0
Author: shahkalpesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-24 06:31:09

Innym sposobem, w jaki widziałem ten wyjątek, niezwiązany z wątkiem, jest serializacja słownika. W tym przypadku był pusty, ale nadal otrzymałem NullReferenceException w metodzie Insert () na deserializowanej instancji.

Prostą zmianą w moim przypadku było stworzenie nowej instancji po deserializacji. Nie jestem pewien, czy serializacja po prostu łamie Słownik, czy są to typy, dla których Słownik jest zdefiniowany.

W moim przypadku typy nie były serializowalny bez serializacji (a ja je podałem), ale może coś w słowniku miało tu problem. Znowu jednak Słownik był pusty i tak się stało.

 0
Author: Todd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-17 19:09:17