Beim Ausführen von SubmitChanges an den DataContext nach dem Aktualisieren einiger Eigenschaften mit einer LINQ-zu-SQL-Verbindung (gegen SQL Server Compact Edition) wird die Meldung "Zeile nicht gefunden oder geändert" angezeigt. 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();
Die Abfrage generiert die folgende SQL:
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
Das offensichtliche Problem ist WHERE 0 = 1. Nachdem der Datensatz geladen wurde, habe ich bestätigt, dass alle Eigenschaften im "deviceSessionRecord" korrekt sind, um den Primärschlüssel einzuschließen. Auch beim Abfangen der "ChangeConflictException" gibt es keine zusätzlichen Informationen darüber, warum dies fehlgeschlagen ist. Ich habe auch bestätigt, dass diese Ausnahme mit genau einem Datensatz in der Datenbank ausgelöst wird (der Datensatz, den ich zu aktualisieren versuche).
Was seltsam ist, ist, dass ich eine sehr ähnliche Update-Anweisung in einem anderen Codeabschnitt habe und sie das folgende SQL generiert und tatsächlich meine SQL Server Compact Edition-Datenbank aktualisiert.
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
Ich habe bestätigt, dass die richtigen primären Feldwerte sowohl im Datenbankschema als auch in der DBML identifiziert wurden, die die LINQ-Klassen generiert.
Ich denke, das ist fast eine zweiteilige Frage:
- Warum wird die Ausnahme ausgelöst?
- Nach der Überprüfung des zweiten Satzes von generiertem SQL scheint es für die Erkennung von Konflikten schön zu sein, alle Felder zu überprüfen, aber ich stelle mir vor, dass dies ziemlich ineffizient wäre. Funktioniert das immer so? Gibt es eine Einstellung, um nur den Primärschlüssel zu überprüfen?
Ich habe in den letzten zwei Stunden damit gekämpft, daher wäre jede Hilfe dankbar.
quelle
Antworten:
Das ist böse, aber einfach:
Überprüfen Sie, ob die Datentypen für alle Felder im O / R-Designer mit den Datentypen in Ihrer SQL-Tabelle übereinstimmen. Überprüfen Sie noch einmal auf nullable! Eine Spalte sollte entweder sowohl im O / R-Designer als auch in SQL nullwertfähig oder in beiden nicht nullwertfähig sein.
Beispielsweise wird eine NVARCHAR-Spalte "title" in Ihrer Datenbank als NULLable markiert und enthält den Wert NULL. Obwohl die Spalte in Ihrer O / R-Zuordnung als NICHT NULL-fähig markiert ist, lädt LINQ sie erfolgreich und setzt die Spaltenzeichenfolge auf null.
Das gleiche Symptom tritt auf, wenn die Datentypen eines Felds nicht mit dem Datentyp in SQL übereinstimmen oder wenn Felder fehlen, da LINQ nicht sicherstellen kann, dass sich die SQL-Daten seit dem Lesen der Daten nicht geändert haben.
quelle
VARCHAR(MAX) NOT NULL
inVARCHAR(MAX) NULL
geändert und erwartet, dass sie funktioniert. Sehr einfacher Fehler.NUMERIC(12,8)
Spalte einerDecimal
Eigenschaft zugeordnet. Ich musste den DbType im Column-Attribut präzisieren[Column(DbType="numeric(12,8)")] public decimal? MyProperty ...
Zunächst ist es hilfreich zu wissen, was das Problem verursacht. Eine Google-Lösung sollte helfen. Sie können die Details (Tabelle, Spalte, alter Wert, neuer Wert) des Konflikts protokollieren, um später eine bessere Lösung für den Konflikt zu finden:
Erstellen Sie einen Helfer zum Umwickeln Ihrer sumbitChanges:
Rufen Sie dann den Änderungscode "Senden" auf:
Protokollieren Sie abschließend die Ausnahme in Ihrem globalen Ausnahmebehandler:
quelle
In DataContext gibt es eine Methode namens Refresh, die hier hilfreich sein kann. Sie können den Datenbankdatensatz neu laden, bevor Änderungen übermittelt werden, und es stehen verschiedene Modi zur Verfügung, um zu bestimmen, welche Werte beibehalten werden sollen. "KeepChanges" scheint für meine Zwecke am klügsten zu sein. Es soll meine Änderungen mit allen nicht widersprüchlichen Änderungen zusammenführen, die in der Zwischenzeit in der Datenbank vorgenommen wurden.
Wenn ich es richtig verstehe. :) :)
quelle
dc.Refresh(RefreshMode.KeepChanges,changedObject);
behoben : vor dc.SubmitChangesDies kann auch durch die Verwendung von mehr als einem DbContext verursacht werden.
Also zum Beispiel:
Dieser Code schlägt von Zeit zu Zeit auf unvorhersehbare Weise fehl, da der Benutzer in beiden Kontexten verwendet, in einem geändert und gespeichert und dann in dem anderen gespeichert wird. Die speicherinterne Darstellung des Benutzers, der "Something" besitzt, stimmt nicht mit dem Inhalt der Datenbank überein, sodass Sie diesen lauernden Fehler erhalten.
Eine Möglichkeit, dies zu verhindern, besteht darin, Code, der jemals als Bibliotheksmethode aufgerufen werden könnte, so zu schreiben, dass ein optionaler DbContext erforderlich ist:
Jetzt nimmt Ihre Methode eine optionale Datenbank, und wenn es keine gibt, erstellt sie selbst eine. Wenn dies der Fall ist, wird nur das wiedergegeben, was übergeben wurde. Die Hilfsmethode erleichtert die Wiederverwendung dieses Musters in Ihrer App.
quelle
Ich habe diesen Fehler behoben, indem ich eine Tabelle vom Server-Explorer zum Designer verschoben und neu erstellt habe.
quelle
Folgendes müssen Sie tun, um diesen Fehler im C # -Code zu überschreiben:
quelle
Ich weiß nicht, ob Sie zufriedenstellende Antworten auf Ihre Frage gefunden haben, aber ich habe eine ähnliche Frage gestellt und sie schließlich selbst beantwortet. Es stellte sich heraus, dass die Standardverbindungsoption NOCOUNT für die Datenbank aktiviert war, was bei jedem mit Linq zu SQL vorgenommenen Update eine ChangeConflictException verursachte. Sie können auf meinen Beitrag hier verweisen .
quelle
Ich habe dies behoben, indem ich
(UpdateCheck = UpdateCheck.Never)
allen[Column]
Definitionen hinzugefügt habe .Fühlt sich jedoch nicht nach einer angemessenen Lösung an. In meinem Fall scheint es damit zu tun zu haben, dass diese Tabelle einer anderen Tabelle zugeordnet ist, aus der eine Zeile gelöscht wird.
Dies ist unter Windows Phone 7.5.
quelle
In meinem Fall wurde der Fehler ausgelöst, als zwei Benutzer mit unterschiedlichen LINQ-zu-SQL-Datenkontexten dieselbe Entität auf dieselbe Weise aktualisierten. Als der zweite Benutzer das Update versuchte, war die Kopie, die er in seinem Datenkontext hatte, veraltet, obwohl sie nach Abschluss des ersten Updates gelesen wurde.
Ich habe die Erklärung und Lösung in diesem Artikel von Akshay Phadke entdeckt: https://www.c-sharpcorner.com/article/overview-of-concurrency-in-linq-to-sql/
Hier ist der Code, den ich meistens aufgehoben habe:
Beim Betrachten meines Ausgabefensters beim Debuggen konnte ich feststellen, dass der aktuelle Wert mit dem Datenbankwert übereinstimmt. Der "ursprüngliche Wert" war immer der Schuldige. Dies war der Wert, den der Datenkontext vor dem Anwenden des Updates gelesen hat.
Vielen Dank an MarceloBarbosa für die Inspiration.
quelle
Ich weiß, dass diese Frage längst beantwortet wurde, aber hier habe ich die letzten Stunden damit verbracht, meinen Kopf gegen eine Wand zu schlagen, und ich wollte nur meine Lösung teilen, die sich als nicht mit einem der Elemente in diesem Thread verbunden herausstellte:
Caching!
Der select () Teil meines Datenobjekts verwendete Caching. Beim Aktualisieren des Objekts trat ein Fehler "Zeile nicht gefunden oder geändert" auf.
In mehreren Antworten wurde die Verwendung unterschiedlicher DataContext-Daten erwähnt, und im Nachhinein ist dies wahrscheinlich der Fall, aber es hat mich nicht sofort dazu gebracht, über das Caching nachzudenken. Hoffentlich hilft dies jemandem!
quelle
Ich bin kürzlich auf diesen Fehler gestoßen und habe festgestellt, dass das Problem nicht bei meinem Datenkontext liegt, sondern bei einer Update-Anweisung, die in einem Trigger ausgelöst wird, nachdem Commit für den Kontext aufgerufen wurde. Der Trigger hat versucht, ein nicht nullwertfähiges Feld mit einem Nullwert zu aktualisieren, und der Kontext ist mit der oben genannten Nachricht fehlerhaft.
Ich füge diese Antwort nur hinzu, um anderen zu helfen, mit diesem Fehler umzugehen und in den obigen Antworten keine Lösung zu finden.
quelle
Ich habe diesen Fehler auch aufgrund der Verwendung von zwei verschiedenen Kontexten erhalten. Ich habe dieses Problem mithilfe eines einzelnen Datenkontexts behoben.
quelle
In meinem Fall lag das Problem bei den serverweiten Benutzeroptionen. Folgende:
https://msdn.microsoft.com/en-us/library/ms190763.aspx
Ich habe die Option NOCOUNT aktiviert, um einige Leistungsvorteile zu erzielen:
und dies führt dazu, dass Linqs Überprüfungen für die betroffenen Zeilen unterbrochen werden (soweit ich dies aus .NET-Quellen herausfinden kann), was zu ChangeConflictException führt
Das Zurücksetzen der Optionen zum Ausschließen des 512-Bit hat das Problem behoben.
quelle
Nachdem ich die Antwort von qub1n verwendet hatte, stellte ich fest, dass das Problem für mich darin bestand, dass ich versehentlich eine Datenbankspalte als dezimal deklariert hatte (18,0). Ich habe einen Dezimalwert zugewiesen, aber die Datenbank hat ihn geändert und den Dezimalteil entfernt. Dies führte zu dem Problem mit der Zeilenänderung.
Fügen Sie dies einfach hinzu, wenn jemand anderes auf ein ähnliches Problem stößt.
quelle
Gehen Sie einfach mit Linq2DB, viel besser
quelle