una tipo terraria produjo outofmemoryexception excepción asp.net sql-server tsql

asp.net - terraria - Se lanzó la excepción del tipo ''System.OutOfMemoryException''. ¿Por qué?



system out of memory exception terraria (5)

Funciona con éxito la primera vez, pero si lo ejecuto nuevamente, sigo obteniendo System.OutOfMemoryException. ¿Cuáles son algunas de las razones por las que esto podría estar pasando?

Independientemente de lo que hayan dicho los demás, el error no tiene nada que ver con olvidarse de eliminar su DBCommand o DBConnection, y no solucionará su error deshaciéndose de ninguno de ellos.

El error tiene todo que ver con su conjunto de datos que contiene casi 600,000 filas de datos. Aparentemente, su conjunto de datos consume más del 50% de la memoria disponible en su máquina. Claramente, se quedará sin memoria cuando devuelva otro conjunto de datos del mismo tamaño antes de que el primero haya sido recolectado. Simple como eso.

Puede solucionar este problema de varias maneras:

  • Considere devolver menos registros. Personalmente, no puedo imaginar un momento en el que devolver los 600K registros haya sido útil para un usuario. Para minimizar los registros devueltos, intente:

    • Limitando su consulta a los primeros 1000 registros. Si hay más de 1000 resultados devueltos de la consulta, informe al usuario para limitar los resultados de búsqueda.

    • Si sus usuarios realmente insisten en ver esa cantidad de datos a la vez, intente buscar los datos. Recuerde: Google nunca muestra los 22 millones de resultados de una búsqueda a la vez, muestra aproximadamente 20 registros a la vez. Es probable que Google no contenga los 22 millones de resultados en la memoria a la vez, probablemente encuentre que es más eficiente en cuanto a la memoria para volver a consultar su base de datos para generar una página nueva.

  • Si solo necesita recorrer los datos y no necesita acceso aleatorio, intente devolver un lector de datos en su lugar. Un lector de datos solo carga un registro en la memoria a la vez.

Si ninguno de ellos es una opción, entonces necesita forzar .NET para liberar la memoria utilizada por el conjunto de datos antes de llamar a su método usando uno de estos métodos:

  • Elimine todas las referencias a su antiguo conjunto de datos. Cualquier cosa que se aferre a un refenence de su conjunto de datos evitará que sea reclamado por la memoria.

  • Si no puede anular todas las referencias a su conjunto de datos, borre todas las filas del conjunto de datos y cualquier objeto vinculado a esas filas en su lugar. Esto elimina las referencias a los datarows y les permite ser comidos por el recolector de basura.

No creo que deba llamar a GC.Collect() para forzar un ciclo de gen. No solo es generalmente una mala idea llamar a GC.Collect() , ya que una presión de memoria suficiente provocará que .NET invoque el recolector de basura por sí mismo.

Nota: Llamar a Dispose en su conjunto de datos no libera ninguna memoria, ni invoca al recolector de elementos innecesarios, ni elimina una referencia a su conjunto de datos. Dispose se usa para limpiar recursos no administrados, pero el DataSet no tiene ningún recurso no administrado. Solo implementa IDispoable porque contiene inherentes de MarshalByValueComponent, por lo que el método Dispose en el conjunto de datos es bastante inútil.

Tengo una consulta dinámica que devuelve alrededor de 590,000 registros. Funciona con éxito la primera vez, pero si lo ejecuto nuevamente, sigo obteniendo System.OutOfMemoryException . ¿Cuáles son algunas de las razones por las que esto podría estar pasando?

El error está sucediendo aquí:

public static DataSet GetDataSet(string databaseName,string storedProcedureName,params object[] parameters) { //Creates blank dataset DataSet ds = null; try { //Creates database Database db = DatabaseFactory.CreateDatabase(databaseName); //Creates command to execute DbCommand dbCommand = db.GetStoredProcCommand(storedProcedureName); dbCommand.CommandTimeout = COMMAND_TIMEOUT; //Returns the list of SQL parameters associated with that stored proecdure db.DiscoverParameters(dbCommand); int i = 1; //Loop through the list of parameters and set the values foreach (object parameter in parameters) { dbCommand.Parameters[i++].Value = parameter; } //Retrieve dataset and set to ds ds = db.ExecuteDataSet(dbCommand); } //Check for exceptions catch (SqlException sqle) { throw sqle; } catch (Exception e) { throw e; // Error is thrown here. } //Returns dataset return ds; }

Aquí está el código que se ejecuta en el botón, haga clic en:

protected void btnSearchSBIDatabase_Click(object sender, EventArgs e) { LicenseSearch ls = new LicenseSearch(); DataTable dtSearchResults = new DataTable(); dtSearchResults = ls.Search(); Session["dtSearchResults"] = dtSearchResults; Response.Redirect("~/FCCSearch/SearchResults.aspx"); } else lblResults.Visible = true; }


¿Dónde falla?

Estoy de acuerdo en que su problema es probablemente que su conjunto de datos de 600,000 filas sea probablemente demasiado grande. Veo que luego lo está agregando a la Sesión. Si está utilizando el estado de sesión Sql, tendrá que serializar también esos datos.

Incluso si dispone de sus objetos correctamente, siempre tendrá al menos 2 copias de este conjunto de datos en la memoria si lo ejecuta dos veces, una vez en sesión, una vez en código de procedimiento. Esto nunca se escalará en una aplicación web.

Hacer los cálculos, 600,000 filas, incluso en 1-128 bits guid por fila produciría 9.6 megabytes (600k * 128/8) de solo datos, sin mencionar el conjunto de datos por encima.

Recorta tus resultados.


Obviamente no estás eliminando cosas.

Considere el comando "usar" cuando usa temporalmente objetos que implementan IDisposable.


Tal vez no esté desechando las clases de conexión / resultado anteriores de la ejecución anterior, lo que significa que aún se quedan en la memoria.


intente dividir sus datos grandes tanto como sea posible porque ya he enfrentado varias veces este tipo de problema. En el que tengo más de 10 registros Lakh con 15 columnas.