web-dev-qa-db-fra.com

Ligne Linq non trouvée ou modifiée

Error Message: Row not found or changed.
Stack Trace:
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 

Cela se produit apparemment au hasard. Je reçois ces erreurs par e-mail, et l'URL signalée semble toujours fonctionner pour moi et devrait également fonctionner pour tout le monde.

Je peux corriger cette erreur en:

  • Aller à ma mise en page dbml
  • Sélection de chaque champ de la table provoquant des conflits
  • Cliquez avec le bouton droit de la souris et définissez la propriété Update Check sur Never.

Cela semble empêcher ces erreurs de se produire.

Cependant, il est difficile de ne pas oublier de continuer à le faire chaque fois que je donne une chance à dmbl, d’ajouter de nouvelles tables, etc. Y at-il un meilleur moyen de résoudre ce problème? J'en reçois peut-être 50 à 100 par jour, ce qui est mauvais pour mes visiteurs.

17
Tom Gullen

Chaque fois que j'ai vu cette erreur, cela signifie que quelque chose a changé dans la base de données entre le moment où j'ai chargé l'enregistrement/l'objet/quoi que ce soit et le moment où j'essayais de le sauvegarder. Sans faute, c'était parce que mon unité de travail était trop grande.

Je ne connais pas la nature exacte de votre application, mais je suppose que vous créez un contexte de données, chargez un enregistrement ou une liste d’enregistrements, effectuez des opérations dessus, rallumez du temps et des cycles de traitement, puis fin en essayant de sauvegarder les données modifiées dans la base de données. Même peut-être même charger une instance d'un enregistrement/objet et la stocker dans une variable de classe pendant un moment, puis à la fin d'un chargement de page ou d'un fil de discussion ou quoi que ce soit essayant de sauvegarder tout ce qui a changé. Le problème est que, comme LINQ en a stocké une copie, il s’agit de la copie qu’elle souhaite mettre à jour. Si les données sous-jacentes changent entre-temps, elles se mettent en colère.

Demandez-vous ceci, et si vous mettiez une transaction de verrouillage sur vos données pour toute la durée de vie de vos objets. Dites ce que vous pouvez modifier, personne ne sera autorisé à le toucher pendant ce temps. Fondamentalement, c'est l'hypothèse ici. Certes, LINQ est un peu plus optimiste à ce sujet. Cela n'a aucun sens de verrouiller la ligne ou le tableau si vous ne mettez jamais à jour les données, mais si vous réfléchissez à ces problèmes. Demandez-vous ce qui ralentirait ou ralentirait de manière significative si vous mettiez des verrous transactionnels stricts sur vos objets, et cela vous mènera probablement au code incriminé.

Ma solution à cela est de garder mon unité de travail aussi petite que possible. Ne chargez pas l'objet et utilisez-le comme copie de travail, puis stockez-le dans la base de données, le tout dans un seul contexte. Au lieu de cela, chargez l'objet et extrayez les informations dont vous avez besoin en une seule étape, puis déterminez les modifications que vous devez appliquer, puis chargez/mettez à jour/enregistrez l'objet. Cela provoque certes plus d'allers-retours dans la base de données, mais vous donne une meilleure assurance que vous utilisez la dernière copie des données. Il sera toujours "dernier entré, gagne", ce qui signifie que si quelqu'un a fait une mise à jour pendant que vous travailliez avec les données, celles-ci pourraient être perdues, mais cela constitue toujours un risque sauf si vous verrouillez l'enregistrement avec une transaction. Cependant, cela vous donne la flexibilité voulue: si quelqu'un modifie des champs non liés dans la même ligne, vous pouvez tous les deux utiliser ces données ensemble.

28
Mike Mooney

J'avais le même problème et je l'ai résolu en comparant dbml à une structure de base de données. Une propriété n'était pas définie sur nullable, ce qui était à l'origine du problème.

Vérifiez donc vos propriétés dbml et nullable.

50
Tomasz Maj

GetTable (). Attach (newEntity, originalEntity);

Si vous n'utilisez pas de champ de version pour la mise à jour, la méthode ci-dessus permet de paramétrer les nouvelles et anciennes entités de détails. Si l'entité d'origine est modifiée à ce stade, vous obtiendrez toujours la même erreur. Cela fonctionne comme un charme, je l'ai essayé. 

2
Serame

Cela peut également se produire si un déclencheur de base de données modifie une colonne d'une ligne que vous mettez à jour, même si vous ne mettez pas à jour cette colonne. 

Vous devrez vérifier que toutes les tables affectées dans votre unité de travail ne comportent pas de déclencheurs. Si vous utilisez des déclencheurs de mise à jour, vous voudrez probablement vous assurer que les colonnes mises à jour sont NeverCheck .

2
Jacob

Parfois, c'est très simple ... Assurez-vous qu'il n'y a pas de serrure sur la table. Dans mon cas, l'interface utilisateur de SQL Server Management Studio contenait des verrous que je ne connaissais pas (dont je ne me souvenais pas) lors du débogage. Le déchargement a effacé ces verrous et tout a recommencé à fonctionner.

1
jco

À l'aide de SQL Profiler, j'ai suivi les transactions SQL vers mon serveur et me suis rendu compte que, sur SubmitChanges(), l'instruction UPDATE transmise contient une mauvaise valeur dans la clause WHERE. C'est parce que j'ai une propriété qui ressemble à ceci:

class Position{
...
    [Column]
    public int Pieces{
        get{
            this.pieces = this.Transformers.Count;

            return this.pieces;
        }
        set{ this.pieces = value; }
    }
...
}

Puisque Transformers est un élément List<Transformers> qui représente une liste de relations un à plusieurs avec une autre table Transformers, je dois remplir manuellement la liste avec chaque Transformer contenant une clé étrangère pour mon objet Position. Si, pour une raison quelconque, je ne le fais pas, j'obtiendrai l'erreur mentionnée car la propriété Pieces est biaisée par rapport à la valeur d'origine. 

Ainsi, l'instruction SQL sur SubmitChanges() cherchera une entrée WHERE Pieces = somevalue mais la valeur réelle de Pieces dans l'entrée sera anothervalue. Donc, fondamentalement, LINQ pensera que vous avez changé quelque chose dans la base de données, car la base de données ne renverra aucune valeur à cette demande.

Comme indiqué, une solution est:

    [Column(UpdateCheck=UpdateCheck.Never)]
    public int Pieces
    {
        get {
            this.pieces= this.Transformers.Count;

            return this.pieces; 
        }
        set { this.pieces= value; }
    }

Bien sûr, cela peut également être facilement résolu en configurant une fonction de lecture simple comme 

getPieces(){
    return this.Transformers.Count();
}

et une propriété "impartiale"

class Position{
...
    [Column]
    public int Pieces{
        get{ return this.pieces; }
        set{ this.pieces = value; }
    }
...
}

J'espère que cela pourra aider quelqu'un. Je poste ceci aussi parce que si quelqu'un d'autre l'avait fait auparavant, cela m'aurait sauvé des heures de ma vie.

1
Flaudre

mise à jour de linq en schéma sql dans le concepteur résoudre le problème dans mon cas

0
Ivan Ivanov

Je recevais cette erreur sur Windows Phone 8. Et il m'a fallu un certain temps pour comprendre quel était le problème. En gros c'était ça:

J'ai suivi un cours appelé TrackingInformation. 1. Sur un serveur, je suis allé chercher une version mise à jour. 2. Mon TileService a mis à jour la vignette secondaire avec ses informations et (!!) une propriété mise à jour et l'a sauvegardée dans la base de données locale du téléphone. 3. J'ai essayé de sauver la première instance de l'objet encore et ici j'ai eu l'erreur "rangée non trouvée ou changée".

Pour moi, il me suffisait de retirer la 3ème partie et cela fonctionnait bien (j'étais déjà enregistré avec la version mise à jour). Mais une propriété ayant changé, une exception a été lancée ... 

Je ne peux pas attendre que EF7 arrive sur Windows Phone, tellement mal à la tête avec l’actuel EF sur WP8.

0
robertk