Question

J'ai un processus qui importe un Spreadhseet Excel et analyse les données dans mes objets de données.La source de ces données est très discutable, car nous faisons passer notre client d'une gestion de données basée sur une feuille de calcul à un système de base de données géré avec des contrôles de données valides.

Au cours de mon processus d'importation, j'effectue quelques vérifications de base des données pour tenir compte de la qualité éventuelle des données que nous importons, mais ma validation globale est effectuée dans DbContext.

Une partie de ce que j'essaie de faire est de fournir le numéro de ligne dans la feuille de calcul indiquant que les données sont mauvaises afin qu'ils puissent facilement déterminer ce qu'ils doivent corriger pour importer le fichier.

Une fois que j'ai les données de la feuille de calcul (model) et l'opportunité avec laquelle ils travaillent dans la base de données (opp), voici le pseudocode de mon processus :

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

Je peux fournir plus de code ici si nécessaire, mais le problème vient de mon DbContext ValidateEntity() méthode (remplacement de DbContext).

Encore une fois, il n'y a rien de mal avec le code que j'ai écrit, pour autant que je sache, mais si une opportunité qui échoue à ce niveau de validation, elle reste parmi les objets non enregistrés dans le fichier. context, ce qui signifie qu'il essaie à plusieurs reprises d'être validé à chaque fois que le ValidateEntity() est appelé.Cela conduit à une répétition du même message d'erreur de validation pour chaque ligne après l'apparition du problème initial.

Y a-t-il un moyen de [modifier]obtenir que le contexte arrête d'essayer de valider l'objet après un échec de validation une fois[modifier]?Je sais que je pourrais attendre la fin et appeler context.SaveChanges() une fois à la fin pour contourner ce problème, mais j'aimerais pouvoir faire correspondre cela avec la ligne dans laquelle il se trouve dans la base de données.

Pour référence, j'utilise Entity Framework 6.1 avec une approche Code First.

MODIFIER Tentant de clarifier davantage pour Marc L.(y compris une mise à jour du bloc de code ci-dessus)

À l'heure actuelle, mon processus parcourra autant de lignes qu'il y en a dans la feuille de calcul.La raison pour laquelle j'appelle ma couche Repository avec chaque objet à enregistrer, au lieu de travailler avec une approche qui appelle uniquement context.SaveChanges() une fois, c'est pour me permettre de déterminer quelle ligne est celle qui provoque une erreur de validation.

Je suis content que la coutume de mon DbContext ValidateEntity() les méthodes détectent les erreurs de validation, mais le problème réside dans le fait qu'elles ne lancent pas le DbEntityValidationException pour la même entité plusieurs fois.

Je voudrais que si l'objet échoue une fois à la validation, le contexte n'essaie plus de sauvegarder l'objet, quel que soit le nombre de fois. context.SaveChanges() est appelé.

Était-ce utile?

La solution

Votre question n'est pas dupe (il s'agit de sauvegarder, pas d'entités chargées) mais vous pouvez suivre les conseils de Jimmy ci-dessus.Autrement dit, une fois qu'une entité est ajoutée au contexte, elle est suivie dans l'état « ajouté » et le seul moyen de l'empêcher de se revalider est de la détacher.C'est un lien SO-interne, mais je vais reproduire l'extrait de code :

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

Cependant, je ne pense pas que ce soit la voie à suivre, car vous utilisez des exceptions pour gérer inutilement l'état (les exceptions sont notoirement coûteuses).

En partant des informations fournies, j'utiliserais une solution plus basée sur des ensembles :

  • modifiez votre classe de modèle afin qu'elle contienne un RowID qui enregistre la ligne originale de la feuille de calcul (il y a probablement d'autres bonnes raisons de l'avoir aussi)
  • désactiver le suivi des entités pour le contexte (tours de détection des changements permettant à chaque Add() être O(1))
  • ajouter toutes les entités
  • appel context.GetValidationErrors() et obtenez toutes vos erreurs à la fois, en utilisant le RowID susmentionné pour identifier les lignes invalides.

Vous n'avez pas indiqué si votre processus doit enregistrer les bonnes lignes ou rejeter le fichier dans son ensemble, mais cela conviendra à l'un ou l'autre : si vous devez enregistrer les bonnes lignes, détachez toutes les lignes invalides à l'aide du code ci-dessus et alors SaveChanges().


Enfin, si vous souhaitez sauvegarder les bonnes lignes et que vous n'êtes pas à l'aise avec la méthode basée sur les ensembles, il serait préférable d'utiliser un nouveau DbContext pour chaque ligne, ou au moins créez un nouveau DbContext après chaque erreur.L'équipe ADO.NET insiste sur le fait que la création de contexte est "relativement bon marché" (désolé, je n'ai pas de citation ni de statistiques sous la main pour cela), donc cela ne devrait pas trop nuire à votre débit.Même ainsi, il restera au moins O(n).Je ne vous en voudrais pas, gérer un contexte large peut également vous ouvrir à d'autres problèmes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top