Domanda

Ho avuto un sito web asp.net in esecuzione in diretta sul nostro intranet per un paio di settimane. Ho appena ricevuto una mail da mio metodo emailer Application_Error con un'eccezione non gestita.

Qui è (ho ripulito alcuni dei percorsi per renderlo visualizzata meglio)

  

eccezione: riferimento non impostato a un'istanza di un oggetto.   Analisi dello stack: a System.Collections.Generic.Dictionary`2.Insert (chiave TKey, TValue valore, booleano aggiuntivo) presso System.Collections.Generic.Dictionary`2.Add (chiave TKey, TValue valore)    a TimesheetDomain.DataMappers.StaffMemberData.ReadStaff (lettore SqlDataReader) in TimesheetDomain \ DataMappers \ StaffMemberData.cs: linea 362

     

a   TimesheetDomain.DataMappers.StaffMemberData.GetStaffMember (String   nome) in   TimesheetDomain \ DataMappers \ StaffMemberData.cs: linea   401

     

a   TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName (String   nome) in   TimesheetDomain \ ServiceLayer \ TimesheetManager.cs: linea   199

     

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

     

a   System.Web.UI.Control.InitRecursive (Controllo   NamingContainer) a   System.Web.UI.Control.InitRecursive (Controllo   NamingContainer) a   System.Web.UI.Page.ProcessRequestMain (booleano   includeStagesBeforeAsyncPoint, booleano   includeStagesAfterAsyncPoint)

In pratica sembra che sia erroring al mio metodo ReadStaff che legge un lettore di dati per costruire oggetti membro del personale. Ecco il pezzo di codice:

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

(linea 362 è terzo ultima riga) Sto utilizzando una mappa di identità (basta leggere il libro cacciatori sui modelli e ho pensato che fosse una buona idea - può aver fatto male, felice per i commenti), ma che non è eccessivamente rilevanti come più tardi io uso l'oggetto newMember altrove quindi se tolgo quel blocco si verificherà la NullReferenceException.

Ho difficoltà a vedere come il newMember terra è nullo nel terzo ultima riga lì (che è la linea che errati).

ReSharper / VS non mi dà un avvertimento che potrebbe essere null - perché ci sono i 3 costruttori, che ho scelto da.

Qualcuno può suggerire dove posso guardare per cercare di risolvere questo errore? E 'successo solo una volta e che il metodo è stato chiamato migliaia di volte in quanto il sito è andato in diretta.

Grazie

[EDIT] Come richiesto, ecco l'IComparer per membro del personale

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

ed è utilizzato nella realizzazione 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);
}
È stato utile?

Soluzione

E 'quasi certamente un problema di threading - vedere questa domanda e la sua risposta accettata .

Dictionary<>.Insert() solleverà NullReferenceException internamente se l'istanza dizionario viene modificata da un altro filo durante l'operazione di inserimento.

Altri suggerimenti

A partire dal .NET 4.0 è possibile utilizzare ConcurrentDictionary e di evitare i problemi di threading associati manipolare lo stesso dizionario da più thread contemporaneamente.

  

E 'successo solo una volta e che   metodo è stato chiamato migliaia di   volte da quando il sito è andato in diretta.

Dopo aver letto questo, posso concludere che, la sua possibile che .NET potrebbe aver esaurito la sua memoria e non è possibile creare un tasto qualsiasi altro dizionario, non può davvero essere ovunque colpa tua. Ma sì, abbiamo fatto ottenere questo tipo di errori quando abbiamo cercato di memorizzare troppe informazioni in variabili di sessione / applicazione aumentando così occupazione di memoria del Web Application. Ma abbiamo ottenuto tali errori quando i nostri numeri sono andati molto alto, come la memorizzazione 10.000 articoli nel dizionario o nell'elenco etc.

Lo schema è buona, ma si deve anche rendersi conto che usiamo database per memorizzare le informazioni in formato relazionale, se cominciamo con la memoria per memorizzare le cose simili, allora stiamo ignorando potente database. Database può memorizzare nella cache i valori per voi pure.

Può sembrare stupido, ma noi abbiamo il nostro Riavviare Windows server ogni 24 ore, a mezzanotte quando non c'è traffico. Questo ci ha aiutato a sbarazzarsi di tali errori. Ripartiamo nostri server regolarmente in un programma di correzione al fine di ottenere tutte le cache / log cancellata.

Non riesco a vedere nulla evidente. Mi piacerebbe correre un po 'di SQL per controllare il database per eventuali dati errati. Il problema può essere un problema maniaco in una forma ingresso correlato. Se il codice è stato eseguito migliaia di volte senza incidenti fino ad ora, mi piacerebbe avvolgo alcuni gestione delle eccezioni aggiuntive / segnalazione attorno al blocco di codice in questione in modo da poter ottenere almeno uno StaffID se / quando succede dopo.

Si potrebbe bruciare un sacco di tempo su qualcosa di simile. L'approccio più opportuno può essere solo lasciarlo sicuro nuovamente nelle condizioni sopra / controllate ..... assumendo il livello di disturbo che provoca è accettabile / gestibile / minore.

Mi rendo conto che sogliono soddisfare il bisogno immediato di conoscere, ma può essere il modo migliore per gestire il problema soprattutto con un tale tasso di fallimento basso.

Come altri hanno detto, il confronto potrebbe essere la causa del problema.
È uno dei criteri per il confronto contengono valore nullo? in particolare, le proprietà di stringa?

vale a dire. Se cognome o cognome o EMAILID è nullo e se è usato in confronto, le cose potrebbero non riuscire quando viene utilizzato all'interno del dizionario per il confronto.

EDIT: Come è Supervisore e staffmember e AdminStaff classe correlata
Nel codice, si sta casting entrambe le istanze di staffmember. La mia ipotesi è che potrebbe essere un problema se il garante e la classe staffmember sono non correlati.

EDIT2: Qual è lo Scrope dell'istanza dizionario? E 'condiviso a livello di livello / sessione dell'applicazione? E 'possibile che più thread potrebbero provare a leggere / scrivere da esso?

Un altro modo che ho visto questa eccezione, estranei a threading, è durante la serializzazione di un dizionario. In questo caso, era vuoto, ma ho ancora ottenuto il NullReferenceException nel metodo Insert () nell'istanza deserializzato.

Il semplice cambiamento nel mio caso era solo quello di creare una nuova istanza dopo la deserializzazione. Non sono sicuro se la serializzazione solo rompe il Dizionario, o se è il tipo che il dizionario è definito per.

Nel mio caso i tipi non erano serializzabile senza surrogati di serializzazione (e mi avevano fornito questi), ma forse qualcosa nel Dizionario avuto un problema qui. Anche in questo caso, però, il dizionario era vuota e questo ancora accaduto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top