문제

저는 몇 주 동안 인트라넷에서 asp.net 웹사이트를 실시간으로 운영하고 있습니다.방금 처리되지 않은 예외가 있는 application_error 이메일 발송자 메소드로부터 이메일을 받았습니다.

여기 있습니다(더 잘 표시되도록 일부 경로를 정리했습니다).

예외 :개체 참조가 개체의 인스턴스로 설정되지 않았습니다.스택 추적:System.Collections.Generic.Dictionary'2.Insert(TKey 키, TValue 값, 부울 추가)에서 System.Collections.Generic.Dictionary'2.Add(TKey 키, TValue 값) TimesheetDomain.DataMappers.StaffMemberData.ReadStaff(SqlDataReader reader)에서 TimesheetDomain\DataMappers\StaffMemberData.cs:줄 362

timesheetdomain.datamappers.staffmemberData.getStaffMember (문자열 이름)에서 timesheetdomain datamappers StaffmemberData.cs : Line 401

에 TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName(문자열 name)에서 TimesheetDomain\ServiceLayer imesheetManager.cs:line 199

UserVerification.GetCurrentUser()에서 \App_Code\UserVerification.cs:line에서 WebTimesheets.OnInit(EventArgs)에서 29 e) 에서 \WebTimesheets\WebTimesheets.master.cs:line 159

에 System.Web.UI.Control.InitRecursive(컨트롤 namingContainer)에서 System.Web.UI.Control.InitRecursive(컨트롤 namingContainer)에서 System.Web.UI.Page.ProcessRequestMain (부울 includeStagesBeforeAsyncPoint, 부울 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행은 마지막 3번째 행) 나는 아이덴티티 맵을 사용하고 있습니다 (패턴에 대한 파울러 책을 읽고 좋은 생각이라고 생각했습니다. 잘못했을 수도 있고 의견에 만족합니다) 나중에 사용할 때 지나치게 관련성이 없습니다. newMember 다른 곳에 개체가 있으므로 해당 개체를 제거하면 차단됩니다. NullReferenceException 일어날 것이다.

도대체 어떻게 될지 고민 중이야 newMember 마지막 세 번째 줄(오류가 발생한 줄)이 null입니다.

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);
}
도움이 되었습니까?

해결책

거의 확실히 스레딩 문제입니다 이 질문과 받아 들여진 답변.

Dictionary<>.Insert() a NullReferenceException 내부적으로 사전 인스턴스가 삽입 작업 중에 다른 스레드에서 수정 된 경우.

다른 팁

.NET 4.0 기준으로 동시 디디컬레이션을 사용하고 여러 스레드에서 동일한 사전을 동시에 조작하는 것과 관련된 스레딩 문제를 피할 수 있습니다.

그것은 한 번만 일어났습니다. 메소드는 수천 개의 사이트가 활성화된 이후 시간.

이 글을 읽은 후에는 .NET이 메모리를 모두 소모하여 더 이상 사전 키를 생성하지 못할 가능성이 있으며 실제로는 사용자 잘못이 아닐 수도 있다는 결론을 내릴 수 있습니다.하지만 그렇습니다. 세션/애플리케이션 변수에 너무 많은 정보를 저장하여 웹 애플리케이션의 메모리 공간을 늘리려고 할 때 이러한 종류의 오류가 발생했습니다.하지만 사전이나 목록에 10,000개의 항목을 저장하는 등 숫자가 너무 높아질 때 이러한 오류가 발생했습니다.

패턴은 좋지만 관계형 형식으로 정보를 저장하기 위해 데이터베이스를 사용한다는 점을 깨달아야 합니다. 비슷한 것을 저장하기 위해 메모리를 사용하기 시작하면 강력한 데이터베이스를 무시하는 것입니다.데이터베이스는 사용자를 위해 값을 캐시할 수도 있습니다.

어리석게 들릴 수도 있지만 트래픽이 없는 자정에 24시간마다 Windows 서버를 다시 시작합니다.이는 그러한 오류를 제거하는 데 도움이 되었습니다.모든 캐시/로그를 지우기 위해 수정 일정에 따라 정기적으로 서버를 다시 시작합니다.

나는 명백한 것을 볼 수 없다. 잘못된 데이터가있는 데이터베이스를 확인하기 위해 SQL을 실행했습니다. 문제는 관련 입력 형태의 괴물 버그 일 수 있습니다. 코드가 지금까지 사고없이 수천 번 실행 된 경우 문제의 코드 블록 주위에 추가 예외 처리/보고를 마무리하므로 다음에 발생하는 경우 직원을 최소한받을 수 있습니다.

이런 식으로 많은 시간을 태울 수 있습니다. 가장 편리한 접근법은 위/제어 된 조건에서 다시 실패하게하는 것일 수 있습니다 ..... 원인이 중단 수준이 허용/관리 가능/미성년이라고 가정합니다.

즉각적인 알아야 할 필요성을 충족시키지 못하지만 특히 실패율이 저하로 문제를 관리하는 가장 좋은 방법 일 수 있습니다.

다른 사람들이 말했듯이, 비교는 문제를 일으킬 수 있습니다.
비교 기준에 널 값이 포함되어 있습니까? 구체적으로 문자열 속성?

즉 FirstName 또는 LastName 또는 EmailId가 NULL 인 경우 비교하여 사용하면 사전 내에서 비교를 위해 사용될 때 상황이 실패 할 수 있습니다.

편집 : 감독자 및 직원 및 Adminstaff 클래스는 어떻게 관련되어 있습니까?
코드에서는 두 인스턴스를 직원에게 캐스팅하고 있습니다. 내 생각에 감독자와 직원 수업이 ~ 아니다 관련된.

edit2 : 사전 인스턴스의 스크로프는 무엇입니까? 응용 프로그램 수준/세션 수준에서 공유됩니까? 여러 스레드가 읽기/쓰기를 시도 할 수 있습니까?

스레딩과 관련 없이 이 예외를 본 또 다른 방법은 사전을 직렬화할 때입니다.이 경우에는 비어 있었지만 역직렬화된 인스턴스의 Insert() 메서드에서 여전히 NullReferenceException이 발생했습니다.

내 경우의 간단한 변경은 역직렬화 후에 새 인스턴스를 만드는 것뿐이었습니다.직렬화가 사전을 깨뜨리는 것인지, 아니면 사전이 정의된 유형인지는 확실하지 않습니다.

내 경우에는 직렬화 대용 없이 유형을 직렬화할 수 없었지만(그리고 이를 제공했습니다) 아마도 사전에 있는 내용에 문제가 있을 수 있습니다.하지만 다시 말하지만, 사전은 비어 있었고 이런 일이 계속 발생했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top