Подтвердить что ты не робот

Как я получил эту ошибку NullReferenceException здесь сразу после конструктора?

У меня был веб-сайт asp.net, который работает в нашей интрасети в течение нескольких недель. Я просто получил электронное письмо от моего метода application_error emailer с необработанным исключением.

Здесь (ive очистил некоторые из путей, чтобы сделать его лучше отображаемым)

Исключение: ссылка на объект не установлена ​​в экземпляр объекта. Трассировка стека: в System.Collections.Generic.Dictionary 2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary 2.Add(ключ TKey, значение TValue)  в TimesheetDomain.DataMappers.StaffMemberData.ReadStaff(SqlDataReader reader) в TimesheetDomain\DataMappers\StaffMemberData.cs: строка 362

в TimesheetDomain.DataMappers.StaffMemberData.GetStaffMember(String имя) в TimesheetDomain\DataMappers\StaffMemberData.cs: линия 401

в TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName(String имя) в TimesheetDomain\ServiceLayer\TimesheetManager.cs: линия 199

в UserVerification.GetCurrentUser() в \App_Code\UserVerification.cs: строка 29 в WebTimesheets.OnInit(EventArgs e) в \ WebTimesheets\WebTimesheets.master.cs: линия 159

в System.Web.UI.Control.InitRecursive(Control namingContainer) в System.Web.UI.Control.InitRecursive(Control namingContainer) в System.Web.UI.Page.ProcessRequestMain(Boolean 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 - третья последняя строка) Я использую идентификационную карту (просто прочитайте книгу фаутеров по шаблонам и подумал, что это хорошая идея, возможно, сделали это неправильно, доволен комментариями), но это не слишком важно, поскольку позже я использую объект newMember в другом месте, поэтому, если я удалю который блокирует нулевое значение, произойдет.

Я изо всех сил пытаюсь понять, как на земле newMember является нулевым в третьей последней строке (которая является ошибкой строки)

Resharper/VS не дает мне предупреждения, что он может быть нулевым, потому что theres 3 конструктора, которые я выбираю.

Может ли кто-нибудь предложить, где я могу попытаться исправить эту ошибку? Это произошло только один раз, и этот метод был назван тысячами раз с момента выхода сайта.

Спасибо

[EDIT] Как запрошено, здесь 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);
    }
4b9b3361

Ответ 1

Это почти наверняка проблема с потоками - см. этот вопрос и принятый ответ.

Dictionary<>.Insert() будет внутренне бросать NullReferenceException, если экземпляр словаря изменяется из другого потока во время операции вставки.

Ответ 2

Начиная с .NET 4.0 вы можете использовать ConcurrentDictionary и избегать проблем с потоками, связанных с одновременным управлением одним и тем же словарем из нескольких потоков.

Ответ 3

Я не вижу ничего очевидного. Я бы запустил SQL, чтобы проверить базу данных на наличие каких-либо плохих данных. Проблема может быть ошибкой ошибки в соответствующей форме ввода. Если код был запущен тысячи раз без инцидентов до сих пор, я бы обернул некоторые дополнительные обработки исключений/отчетности вокруг блока кода, о котором идет речь, чтобы вы могли хотя бы получить staffId, если/когда это произойдет.

Вы могли бы записать много времени на что-то вроде этого. Наиболее целесообразный подход может состоять только в том, чтобы позволить ему снова потерпеть неудачу в вышеуказанных/контролируемых условиях..... предполагая, что уровень нарушения, который он вызывает, является приемлемым/управляемым/незначительным.

Я ценю, что не удовлетворит непосредственную необходимость знать, но это может быть лучший способ справиться с проблемой, особенно с такой низкой частотой отказа.

Ответ 4

Как говорили другие, сравнение может вызвать проблему.
Является ли какой-либо из критериев сравнения нулевым значением? в частности, свойства строки?

то есть. Если firstname или lastname или emailId являются нулевыми, и если они используются для сравнения, все может сбой при использовании в словаре для сравнения.

EDIT: Как связан класс Supervisor и StaffMember и AdminStaff?
В коде вы бросаете оба экземпляра в StaffMember. Я предполагаю, что это может быть проблемой, если класс Supervisor и StaffMember связан с не.

EDIT2: Что такое scrope словаря словаря? Разделяется ли он на уровне приложений/сеансах? Возможно ли, что несколько потоков могут попытаться прочитать/записать из него?

Ответ 5

Это произошло только один раз и метод был назван тысячами раз с момента выхода сайта.

Прочитав это, я могу заключить, что возможно, что .NET, возможно, исчерпал свою память, и он больше не мог создать ключ словаря, на самом деле это не может быть вашей ошибкой. Но да, мы получили такие ошибки, когда пытались хранить слишком много информации в переменных сеанса/приложения, увеличивая таким образом объем памяти веб-приложения. Но у нас были такие ошибки, когда наши номера были очень высокими, например, хранение 10 000 предметов в словаре или списке и т.д.

Образец хорош, но вы также должны понимать, что мы используем базу данных для хранения информации в реляционном формате, если мы начнем использовать память для хранения подобных вещей, тогда мы игнорируем мощную базу данных. База данных также может кэшировать значения для вас.

Это может показаться глупым, но мы перезагружаем сервер Windows каждые 24 часа, в полночь, когда нет трафика. Это помогло нам избавиться от таких ошибок. Мы регулярно перезапускаем наши серверы в расписании исправлений, чтобы очистить все кешированные/журнальные файлы.

Ответ 6

Другой способ, которым я видел это исключение, не связанное с потоковой обработкой, - это сериализация словаря. В этом случае он был пуст, но я все еще получил исключение NullReferenceException в методе Insert() в десериализованном экземпляре.

Простым изменением в моем случае было просто создать новый экземпляр после десериализации. Я не уверен, что сериализация просто ломает словарь, или если это типы, для которых определяется словарь.

В моем случае типы не были сериализованы без суррогатов сериализации (и я их предоставил), но, возможно, что-то в словаре было проблемой здесь. Опять же, Словарь был пуст, и это все еще произошло.