Pregunta

Tengo un proceso que consiste en importar un Spreadhseet de Excel y analizar los datos en mis objetos de datos.La fuente de estos datos es muy cuestionable, ya que estamos trasladando a nuestro cliente de una gestión de datos basada en hojas de cálculo a un sistema de base de datos gestionado con comprobaciones de datos válidos.

Durante mi proceso de importación, hago algunas comprobaciones básicas de los datos para tener en cuenta qué tan malos podrían ser los datos que estamos importando, pero mi validación general se realiza en DbContext.

Parte de lo que estoy tratando de hacer es proporcionar el número de fila en la hoja de cálculo en el que los datos son incorrectos para que puedan determinar fácilmente qué deben corregir para importar el archivo.

Una vez que tenga los datos de la hoja de cálculo (model) y la oportunidad con la que están trabajando desde la base de datos (opp), aquí está el pseudocódigo de mi proceso:

foreach (var model in Spreadsheet.Rows) { // Again, pseudocode
    if(opp != null && ValidateModel(model, opp, row)) {
        // Copy properties to the database object

        // This is in a Repository-layer method, not directly in my import process.
        // Just written here for clarity instead of several nested method calls.
        context.SaveChanges(); 
    }
}

Puedo proporcionar más código aquí si es necesario, pero el problema surge en mi DbContext. ValidateEntity() método (anulación de DbContext).

Nuevamente, no hay nada malo con el código que he escrito, hasta donde yo sé, pero si una Oportunidad no superó este nivel de validación, entonces permanece como parte de los objetos no guardados en el context, lo que significa que intenta repetidamente ser validado cada vez que el ValidateEntity() se llama.Esto lleva a que se repita el mismo mensaje de error de validación para cada fila después de que ocurre el problema inicial.

¿Hay alguna manera de [editar]obtener el contexto para dejar de intentar validar el objeto después de que falle la validación una vez[editar]?Sé que podría esperar hasta el final y llamar context.SaveChanges() una vez al final para solucionar este problema, pero me gustaría poder hacer coincidir esto con la fila en la base de datos.

Como referencia, estoy usando Entity Framework 6.1 con un enfoque Code First.

EDITAR Intentando aclarar más a Marc L.(incluida una actualización del bloque de código anterior)

En este momento, mi proceso recorrerá tantas filas como haya en la hoja de cálculo.La razón por la que llamo a mi capa de Repositorio con cada objeto a guardar, en lugar de trabajar con un enfoque que solo llama context.SaveChanges() Una vez es permitirme la capacidad de determinar qué fila es la que está causando un error de validación.

Me alegro de que mi DbContext sea personalizado. ValidateEntity() Los métodos están detectando los errores de validación, pero el problema reside en el hecho de que no arroja el DbEntityValidationException para la misma entidad varias veces.

Me gustaría que si el objeto falla la validación una vez, el contexto ya no intente guardar el objeto, sin importar cuántas veces context.SaveChanges() se llama.

¿Fue útil?

Solución

Su pregunta no es una tontería (se trata de guardar, no de entidades cargadas), pero puede seguir el consejo de Jimmy anterior.Es decir, una vez que se agrega una entidad al contexto, se rastrea en el estado "agregada" y la única forma de evitar que se vuelva a validar es separándola.Es un enlace SO interno, pero reproduciré el fragmento de código:

dbContext.Entry(entity).State = EntityState.Detached;

Sin embargo, no creo que ese sea el camino que desea seguir, porque está utilizando excepciones para administrar el estado innecesariamente (las excepciones son notoriamente costosas).

A partir de la información proporcionada, usaría una solución más basada en conjuntos:

  • modifique su clase de modelo para que contenga un RowID que registre la fila original de la hoja de cálculo (probablemente también haya otras buenas razones para tener esto)
  • desactivar el seguimiento de entidades para el contexto (turnos de detección de cambios que permiten a cada Add() ser O(1))
  • agregar todas las entidades
  • llamar context.GetValidationErrors() y obtenga todos sus errores a la vez, utilizando el RowID antes mencionado para identificar las filas no válidas.

No indicó si su proceso debe guardar las filas buenas o rechazar el archivo en su totalidad, pero esto se adaptará a cualquiera de las dos opciones; es decir, si necesita guardar las filas buenas, separe todas las filas no válidas usando el código anterior y entonces SaveChanges().


Finalmente, si desea guardar las filas buenas y no se siente cómodo con el método basado en conjuntos, sería mejor utilizar un nuevo DbContext para cada fila, o al menos crear una nueva DbContext después de cada error.El equipo de ADO.NET insiste en que la creación de contexto es "relativamente barata" (lo siento, no tengo una cita ni estadísticas disponibles para esto), por lo que esto no debería dañar demasiado su rendimiento.Aun así, al menos permanecerá O(n).No te culpo, gestionar un contexto amplio también puede abrirte a otros problemas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top