c# - validar - system.nullreferenceexception solucion
¿Cómo obtuve este error NullReferenceException aquí justo después del constructor? (6)
Solo sucedió una vez y ese método ha sido llamado miles de veces desde que el sitio se activó.
Después de leer esto, puedo concluir que es posible que .NET haya agotado su memoria y no haya podido crear ninguna otra clave del diccionario, puede que en realidad no sea tu culpa en ningún otro lugar. Pero sí obtuvimos este tipo de errores cuando intentamos almacenar demasiada información en las variables de sesión / aplicación, lo que aumentaba el espacio de memoria de la aplicación web. Pero obtuvimos esos errores cuando nuestros números fueron muy altos, como almacenar 10.000 elementos en Dictionary o List, etc.
El patrón es bueno, pero también debe tener en cuenta que usamos la base de datos para almacenar información en formato relacional, si comenzamos a usar memoria para almacenar cosas similares, entonces estamos ignorando una base de datos poderosa. La base de datos también puede guardar valores en caché.
Puede sonar tonto pero nuestro servidor de Windows se reinicia cada 24 horas, a medianoche cuando no hay tráfico. Eso nos ayudó a deshacernos de esos errores. Reiniciamos nuestros servidores regularmente en un horario de arreglos para que todos los registros / caché se borren.
He tenido un sitio web asp.net en vivo en nuestra intranet desde hace un par de semanas. Acabo de recibir un correo electrónico de mi application_error emailer con una excepción no controlada.
Aquí está (he limpiado algunos de los caminos para que se muestre mejor)
Excepción: referencia de objeto no establecida en una instancia de un objeto. Stack Trace: en System.Collections.Generic.Dictionary`2.Insert (TKey key, TValue value, Boolean add) en System.Collections.Generic.Dictionary`2.Add (tecla TKey, valor de TValue) en TimesheetDomain.DataMappers.StaffMemberData .ReadStaff (lector de SqlDataReader) en TimesheetDomain / DataMappers / StaffMemberData.cs: línea 362
en TimesheetDomain.DataMappers.StaffMemberData.GetStaffMember (String name) en TimesheetDomain / DataMappers / StaffMemberData.cs: línea 401
en TimesheetDomain.ServiceLayer.TimesheetManager.GetUserFromName (String name) en TimesheetDomain / ServiceLayer / TimesheetManager.cs: línea 199
en UserVerification.GetCurrentUser () en / App_Code / UserVerification.cs: línea 29 en WebTimesheets.OnInit (EventArgs e) en / WebTimesheets / WebTimesheets.master.cs: línea 159
en System.Web.UI.Control.InitRecursive (Control namingContainer) en System.Web.UI.Control.InitRecursive (Control namingContainer) en System.Web.UI.Page.ProcessRequestMain (Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Básicamente, parece que está cometiendo errores en mi método ReadStaff, que lee un lector de datos para crear objetos de miembros del personal. Aquí está el pedacito de código:
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;
}
(La línea 362 es la 3º línea) Estoy usando un mapa de identidad (solo leí Fowlers book sobre patrones y pensé que era una buena idea, puede haberlo hecho mal, feliz por los comentarios) pero eso no es demasiado relevante ya que más adelante uso el objeto newMember
otro lugar, de modo que si newMember
ese bloque se producirá la NullReferenceException
.
Estoy luchando para ver cómo en la tierra newMember
es nulo en la tercera línea anterior allí (que es la línea que tenía errores).
Resharper / VS no me da una advertencia de que podría ser null
, porque están los 3 constructores que elijo.
¿Alguien puede sugerir dónde puedo mirar para intentar reparar este error? Solo sucedió una vez y ese método ha sido llamado miles de veces desde que el sitio se activó.
Gracias
[EDIT] Según lo solicitado, aquí está el IComparer para el miembro del personal
/// <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");
}
}
y se usa en la implementación 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);
}
A partir de .NET 4.0, puede utilizar ConcurrentDictionary y evitar los problemas de subprocesamiento asociados con la manipulación del mismo diccionario desde varios subprocesos simultáneamente.
Como otros han dicho, la comparación podría estar causando el problema.
¿Alguno de los criterios de comparación contiene valor nulo? específicamente, las propiedades de la cadena?
es decir, si firstname o lastname o emailId es nulo y si se usa en comparación, las cosas podrían fallar si se usan dentro del diccionario para su comparación.
EDITAR: ¿Cómo se relaciona la clase Supervisor y StaffMember y AdminStaff?
En el código, estás transfiriendo ambas instancias a StaffMember. Supongo que podría ser un problema si la clase Supervisor y StaffMember no están relacionadas.
EDIT2: ¿Cuál es el scrope de la instancia del diccionario? ¿Se comparte a nivel de aplicación / sesión? ¿Es posible que varios hilos intenten leer / escribir desde él?
Es casi seguro un problema de enhebrado: vea esta pregunta y su respuesta aceptada .
Dictionary<>.Insert()
lanzará una NullReferenceException
internamente si la instancia del diccionario se modifica desde otro hilo durante la operación de inserción.
No puedo ver nada obvio. Ejecutaría algo de SQL para verificar la base de datos en busca de datos malos. El problema puede ser un error extraño en un formulario de entrada relacionado. Si el código se ha ejecutado miles de veces sin incidentes hasta ahora, incluiría algunos informes / manejo de excepciones adicionales en torno al bloque de código en cuestión para que al menos pueda obtener un Id. De personal si es el siguiente.
Podría perder mucho tiempo en algo como esto. El enfoque más conveniente puede ser simplemente dejar que falle de nuevo bajo las condiciones controladas / arriba ... asumiendo que el nivel de interrupción que causa es aceptable / manejable / menor.
Aprecio que no satisfará la necesidad inmediata de saber, pero puede ser la mejor manera de manejar el problema, especialmente con una tasa de fracaso tan baja.
Otra forma en que he visto esta excepción, sin relación con el subprocesamiento, es al serializar un diccionario. En este caso, estaba vacío, pero todavía tengo la NullReferenceException en el método Insert () en la instancia deserializada.
El cambio simple en mi caso fue simplemente crear una nueva instancia después de la deserialización. No estoy seguro de si la serialización simplemente rompe el Diccionario, o si se trata de los tipos para los que está definido el Diccionario.
En mi caso, los tipos no eran serializables sin sustitutos de serialización (y yo los había proporcionado), pero tal vez algo en el Diccionario tenía un problema aquí. De nuevo, sin embargo, el Diccionario estaba vacío y esto todavía sucedió.