Gibt es einen Grund, warum ein vorhandenes Objekt in ListT in diesem Codeblock nicht gefunden wird?

9

Wir haben ein Gitter, das an einen List<T> der Gegenstände gebunden ist. Wenn der Benutzer auf "Aktualisieren" klickt, werden Änderungen von der Datenbank erhalten und die gebundene Liste wird aktualisiert. Ich stoße auf ein Problem, bei dem doppelte Elemente zum Raster hinzugefügt werden, und ich kann nicht herausfinden, warum.

Der Datenbankaufruf gibt zwei Werte zurück: a List<int> der Datensatz-IDs, die geändert wurden, und List<MyClass> der aktualisierten Daten für die Datensätze, die geändert wurden. Der existierende Codecode, den ich gerade entpacke, der herausfindet, was aktualisiert werden muss, sieht ungefähr so ​​aus:

%Vor%

Das Ergebnis des Aufrufs von FindUpdates() ist ein Dictionary<Id, Data> der vorhandenen Datensätze, ein Dictionary<Id, Data> der aktualisierten Datensätze, die ersetzt werden sollen, und ein List<int> der IDs, für die Elemente hinzugefügt, entfernt, oder Von der Datenquelle aktualisiert.

Gelegentlich wird ein Datensatz zweimal zum Raster hinzugefügt und ich kann nicht für das Leben von mir herausfinden, wo dieser Code falsch läuft.

Ich habe die Protokolldatei von einer dieser Instanzen abgerufen und kann die folgende Sequenz von Ereignissen deutlich sehen:

  • Eintrag # 2 wurde der Liste der Daten hinzugefügt
  • 20 Minuten später wird Element # 2 erneut zur Liste der Daten hinzugefügt

WriteToLog() von der 2. add sagt mir das

  • updatedIds enthält die Werte 1, 2 und 3
  • adds enthält 1 und 2
  • updates enthält 3

Basierend auf anderen Protokolleinträgen kann ich deutlich sehen, dass Element Nr. 2 zuvor hinzugefügt und nie entfernt wurde. Er sollte also in der existingRecords -Variable in der updates -Variable erscheinen, nicht in der adds . Außerdem wurde Punkt # 2 zwischen dem ersten und dem zweiten Add-in mehrmals erfolgreich aktualisiert, sodass der Code in der Theorie funktionieren sollte. Ich habe auch einen Screenshot der Benutzeroberfläche und zeige beide Kopien von Artikel 2 im Raster der Daten.

Notizen ...

  • IsDisposed wird nur in der überschriebenen Methode .Dispose() für das Element auf "true" gesetzt. Ich glaube nicht, dass dies passiert wäre.

    Bearbeiten: Ich habe seither eine Protokollanweisung hinzugefügt und kann überprüfen, ob IsDisposed in diesem Fall nicht auf true gesetzt ist.

  • Dies ist schon ein paar Mal passiert, aber es ist nicht nur eine einmalige Sache. Ich kann das Problem jedoch nicht nach Bedarf reproduzieren.

  • Das Raster der Datensätze kann ziemlich groß sein und im Durchschnitt einige tausend Elemente enthalten.

  • Ich habe die Idee nicht ausgeschlossen, dass der DB-Aufruf ungültige Werte oder Listen zurückgibt, die nicht die gleichen Elemente haben, aber ich sehe nicht, wie dies das Ergebnis beeinflussen könnte

  • Das einzige Mal, als ich diesen Fehler in Aktion sehen konnte, führten wir einige Tests durch und andere Benutzer änderten Datensatz # 2 ziemlich häufig

  • Dies alles läuft in einem Hintergrund-Thread

  • Basierend auf dem Protokoll wurde dies nur einmal ausgeführt. Es lief vorher eine Minute vorher, und nächste 2 Minuten später.

  • Aus der Log-Datei kann ich sehen, dass Element 2 einige Male korrekt aktualisiert wurde, bevor es ein zweites Mal falsch hinzugefügt wurde. Daher hat dieser Code schon einige Male mit dem vorhandenen Datensatz funktioniert.

Gibt es in dem oben gezeigten Code überhaupt etwas, das dazu führen könnte? Oder vielleicht ein selten bekanntes Problem in C #, wo dies passieren könnte, dass mir nicht bekannt ist?

    
Rachel 05.03.2014, 15:36
quelle

2 Antworten

1

Es gibt keinen Grund, warum ein vorhandenes Element nicht in List<T> mit dem obigen Code gefunden wird.

Ich hätte Alarmglocken in meinem Kopf haben sollen, als ich bemerkte, dass die Ausgabewerte Dictionary<int,int> der Werte enthielten, die die ID eines Elements enthielten, und den Index des Elements innerhalb der vorhandenen Liste .

Was passiert ist, wurden Artikel mit existingRecords[existing[id]] entfernt, wobei existing[id] den Index des Artikels innerhalb von existingRecords zurückgeben würde. Damit dies funktioniert, müssen Artikel aus dem größten Index nach unten entfernt werden. Wenn ein kleinerer Index vor einem größeren entfernt wird, ist der größere Index nun um 1 Position falsch und das falsche Element wird entfernt.

Warum habe ich doppelte Artikel erhalten, weil zwei Sammlungen gepflegt wurden, eine, die verwendet wurde, um festzustellen, ob Artikel neu / aktualisiert / gelöscht wurden, und ein anderer, der zur Anzeige in der Benutzeroberfläche gebunden wurde. Die erste Sammlung wurde falsch aktualisiert, die zweite nicht, was zu Szenarios führte, in denen Elemente mehrfach zur UI-Sammlung hinzugefügt werden konnten.

Meine kurzfristige Lösung bestand darin, nach der removes -Auflistung zu sortieren, um sicherzustellen, dass sie nach dem Index jedes Elements in absteigender Reihenfolge sortiert wurde. Meine langfristige Lösung wird sein, den Code neu zu schreiben. :)

    
Rachel 15.05.2014, 14:31
quelle
0
%Vor%

würde versuchen, das Objekt a in der Liste zu finden, das a.Equals (r). Wenn MyClass Equals nicht überschreibt, können Sie nicht sicher sein, dass zwei verschiedene Objekte derselben Klasse gleich sind. Ich bin mir da nicht ganz sicher: aber ich denke, dass equals GetHashCode () verwendet. Wenn Sie sich dafür entscheiden, einen von ihnen zu überschreiben, sollten Sie den anderen überschreiben.

hier ist MSDN darüber: Ссылка

    
Donnie Hanner 05.03.2014 16:28
quelle