Lors de l'exécution de SubmitChanges vers DataContext après la mise à jour de quelques propriétés avec une connexion LINQ to SQL (par rapport à SQL Server Compact Edition), j'obtiens un message «Ligne introuvable ou modifiée». ChangeConflictException.
var ctx = new Data.MobileServerDataDataContext(Common.DatabasePath);
var deviceSessionRecord = ctx.Sessions.First(sess => sess.SessionRecId == args.DeviceSessionId);
deviceSessionRecord.IsActive = false;
deviceSessionRecord.Disconnected = DateTime.Now;
ctx.SubmitChanges();
La requête génère le SQL suivant:
UPDATE [Sessions]
SET [Is_Active] = @p0, [Disconnected] = @p1
WHERE 0 = 1
-- @p0: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p1: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:12:02 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
Le problème évident est le WHERE 0 = 1 , après le chargement de l'enregistrement, j'ai confirmé que toutes les propriétés du "deviceSessionRecord" sont correctes pour inclure la clé primaire. Aussi lors de la capture de "ChangeConflictException", il n'y a aucune information supplémentaire sur la raison pour laquelle cela a échoué. J'ai également confirmé que cette exception est levée avec exactement un enregistrement dans la base de données (l'enregistrement que je tente de mettre à jour)
Ce qui est étrange, c'est que j'ai une instruction de mise à jour très similaire dans une section de code différente et qu'elle génère le SQL suivant et met effectivement à jour ma base de données SQL Server Compact Edition.
UPDATE [Sessions]
SET [Is_Active] = @p4, [Disconnected] = @p5
WHERE ([Session_RecId] = @p0) AND ([App_RecId] = @p1) AND ([Is_Active] = 1) AND ([Established] = @p2) AND ([Disconnected] IS NULL) AND ([Member_Id] IS NULL) AND ([Company_Id] IS NULL) AND ([Site] IS NULL) AND (NOT ([Is_Device] = 1)) AND ([Machine_Name] = @p3)
-- @p0: Input Guid (Size = 0; Prec = 0; Scale = 0) [0fbbee53-cf4c-4643-9045-e0a284ad131b]
-- @p1: Input Guid (Size = 0; Prec = 0; Scale = 0) [7a174954-dd18-406e-833d-8da650207d3d]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:50 PM]
-- @p3: Input String (Size = 0; Prec = 0; Scale = 0) [CWMOBILEDEV]
-- @p4: Input Boolean (Size = 0; Prec = 0; Scale = 0) [False]
-- @p5: Input DateTime (Size = 0; Prec = 0; Scale = 0) [9/4/2008 5:20:52 PM]
-- Context: SqlProvider(SqlCE) Model: AttributedMetaModel Build: 3.5.21022.8
J'ai confirmé que les valeurs de champs primaires appropriées ont été identifiées à la fois dans le schéma de base de données et dans le DBML qui génère les classes LINQ.
Je suppose que c'est presque une question en deux parties:
- Pourquoi l'exception est-elle levée?
- Après avoir examiné le deuxième ensemble de SQL généré, il semble que pour détecter les conflits, il serait bien de vérifier tous les champs, mais j'imagine que ce serait assez inefficace. Est-ce ainsi que cela fonctionne toujours? Existe-t-il un paramètre pour vérifier simplement la clé primaire?
Je me bats avec ça depuis deux heures, donc toute aide serait appréciée.
la source
Réponses:
C'est méchant, mais simple:
Vérifiez si les types de données de tous les champs du O / R-Designer correspondent aux types de données de votre table SQL. Vérifiez à nouveau pour nullable! Une colonne doit être Nullable à la fois dans O / R-Designer et SQL, ou non Nullable dans les deux.
Par exemple, une colonne NVARCHAR "titre" est marquée comme NULLable dans votre base de données et contient la valeur NULL. Même si la colonne est marquée comme NOT NULLable dans votre O / R-Mapping, LINQ la chargera avec succès et définira la chaîne de colonne sur null.
Le même symptôme apparaît lorsque les types de données d'un champ ne correspondent pas au type de données dans SQL, ou si des champs sont manquants, car LINQ ne pourra pas s'assurer que les données SQL n'ont pas changé depuis la lecture des données.
la source
VARCHAR(MAX) NOT NULL
enVARCHAR(MAX) NULL
et en m'attendant à ce qu'elle fonctionne. Erreur très simple.NUMERIC(12,8)
colonne mappée à uneDecimal
propriété. J'ai dû préciser le DbType dans l'attribut Column[Column(DbType="numeric(12,8)")] public decimal? MyProperty ...
Premièrement, il est utile de savoir ce qui cause le problème. La solution Google devrait aider, vous pouvez enregistrer les détails (table, colonne, ancienne valeur, nouvelle valeur) sur le conflit pour trouver une meilleure solution pour résoudre le conflit plus tard:
Créez un assistant pour envelopper vos sumbitChanges:
Et puis appelez le code de soumission des modifications:
Enfin, enregistrez l'exception dans votre gestionnaire d'exceptions global:
la source
Il existe une méthode sur DataContext appelée Refresh qui peut aider ici. Il vous permet de recharger l'enregistrement de la base de données avant que les modifications ne soient soumises et propose différents modes pour déterminer les valeurs à conserver. "KeepChanges" semble le plus intelligent pour mes besoins, il est destiné à fusionner mes modifications avec tout changement non conflictuel qui s'est produit dans la base de données entre-temps.
Si je comprends bien. :)
la source
dc.Refresh(RefreshMode.KeepChanges,changedObject);
avant dc.SubmitChangesCela peut également être dû à l'utilisation de plusieurs DbContext.
Donc par exemple:
Ce code échouera de temps en temps, d'une manière qui semble imprévisible, car l'utilisateur est utilisé dans les deux contextes, modifié et enregistré dans l'un, puis enregistré dans l'autre. La représentation en mémoire de l'utilisateur qui possède "Something" ne correspond pas à ce qui est dans la base de données, et vous obtenez donc ce bogue caché.
Une façon d'éviter cela est d'écrire tout code qui pourrait être appelé en tant que méthode de bibliothèque de telle manière qu'il prenne un DbContext facultatif:
Alors maintenant, votre méthode prend une base de données optionnelle, et s'il n'y en a pas, elle en crée une elle-même. Si tel est le cas, il réutilise simplement ce qui a été transmis. La méthode d'assistance facilite la réutilisation de ce modèle dans votre application.
la source
J'ai résolu cette erreur en déplaçant à nouveau sur une table de l'explorateur de serveur au concepteur et en reconstruisant.
la source
Voici ce dont vous avez besoin pour remplacer cette erreur sur le code C #:
la source
Je ne sais pas si vous avez trouvé des réponses satisfaisantes à votre question, mais j'ai posté une question similaire et y ai finalement répondu moi-même. Il s'est avéré que l'option de connexion par défaut NOCOUNT était activée pour la base de données, ce qui a provoqué une exception ChangeConflictException pour chaque mise à jour effectuée avec Linq vers Sql. Vous pouvez consulter mon message ici .
la source
J'ai corrigé cela en ajoutant
(UpdateCheck = UpdateCheck.Never)
à toutes les[Column]
définitions.Ne semble pas être une solution appropriée, cependant. Dans mon cas, cela semble être lié au fait que cette table a une association avec une autre table à partir de laquelle une ligne est supprimée.
C'est sur Windows Phone 7.5.
la source
Dans mon cas, l'erreur a été générée lorsque deux utilisateurs ayant des contextes de données LINQ-to-SQL différents ont mis à jour la même entité de la même manière. Lorsque le deuxième utilisateur a tenté la mise à jour, la copie qu'il avait dans son contexte de données était périmée même si elle avait été lue après la fin de la première mise à jour.
J'ai découvert l'explication et la solution dans cet article d'Akshay Phadke: https://www.c-sharpcorner.com/article/overview-of-concurrency-in-linq-to-sql/
Voici le code que j'ai le plus souvent levé:
Lorsque j'ai regardé ma fenêtre de sortie pendant le débogage, je pouvais voir que la valeur actuelle correspondait à la valeur de la base de données. La «valeur originale» a toujours été le coupable. C'était la valeur lue par le contexte de données avant d'appliquer la mise à jour.
Merci à MarceloBarbosa pour l'inspiration.
la source
Je sais que cette question a depuis longtemps reçu une réponse, mais ici, j'ai passé les dernières heures à me cogner la tête contre un mur et je voulais juste partager ma solution qui s'est avérée ne pas être liée à l'un des éléments de ce fil:
Mise en cache!
La partie select () de mon objet de données utilisait la mise en cache. Lorsqu'il s'agissait de mettre à jour l'objet, une erreur de ligne non trouvée ou modifiée apparaissait.
Plusieurs des réponses ont mentionné l'utilisation de différents DataContext et rétrospectivement, c'est probablement ce qui se passait, mais cela ne m'a pas immédiatement amené à penser à la mise en cache, alors j'espère que cela aidera quelqu'un!
la source
J'ai récemment rencontré cette erreur et j'ai découvert que le problème n'était pas lié à mon contexte de données, mais à une instruction de mise à jour se déclenchant dans un déclencheur après l'appel de Commit sur le contexte. Le déclencheur essayait de mettre à jour un champ non Nullable avec une valeur Null et provoquait une erreur de contexte avec le message mentionné ci-dessus.
J'ajoute cette réponse uniquement pour aider les autres à gérer cette erreur et à ne pas trouver de résolution dans les réponses ci-dessus.
la source
J'ai également eu cette erreur en raison de l'utilisation de deux contextes différents. J'ai résolu ce problème en utilisant un contexte de données unique.
la source
Dans mon cas, le problème était lié aux options utilisateur à l'échelle du serveur. Suivant:
https://msdn.microsoft.com/en-us/library/ms190763.aspx
J'ai activé l'option NOCOUNT dans l'espoir d'obtenir des avantages en termes de performances:
et cela s'avère casser les vérifications de Linq pour les lignes affectées (autant que je puisse le comprendre à partir de sources .NET), conduisant à ChangeConflictException
La réinitialisation des options pour exclure les 512 bits a résolu le problème.
la source
Après avoir utilisé la réponse de qub1n, j'ai trouvé que le problème pour moi était que j'avais déclaré par inadvertance qu'une colonne de base de données était décimale (18,0). J'attribuais une valeur décimale, mais la base de données la changeait, supprimant la partie décimale. Cela a entraîné le problème de changement de ligne.
Il suffit d'ajouter ceci si quelqu'un d'autre rencontre un problème similaire.
la source
allez simplement avec Linq2DB, beaucoup mieux
la source