2012-06-29 14 views
5

Da EF keine eindeutigen Schlüsseleinschränkungen unterstützt, müssen wir bei der Save-Methode eine Ausnahme abfangen und dem Benutzer eine Fehlermeldung anzeigen.EF CodeFirst beim Behandeln von Datenbankausnahmen beim Speichern von Änderungen

Die Probleme mit diesem Ansatz sind:

  • wie können wir wissen, welcher Datensatz eine Ausnahme ausgelöst hat
  • wie können wir wissen, welche Art von Problem, eine Ausnahme ausgelöst hat (ex ich zwei eindeutige Einschränkungen auf gleiche haben könnte Rekord, so muss ich den Benutzer sagen, die man kaputt ist)

DBMS ist SqlServer 2008

Wie diese Probleme zu lösen?

Antwort

2

Wenn Sie zulassen, dass ein Benutzer Werte eingeben können, die in der Datenbank eindeutig sein müssen, sollten Sie diese Eingabe validieren, bevor Sie die Änderungen speichern:

if (context.Customers.Any(c => c.SomeUniqueProperty == userInput)) 
    // return to user with a message to change the input value 
else 
    context.SaveChanges(); 

Dies ist nicht nur der Fall für Werte mit eindeutiger Zuordnung in der Datenbank, aber auch zur Eingabe von Fremdschlüsselwerten, die sich auf vorhandene Zieldatensätze oder Primärschlüsselwerte beziehen müssen, wenn der Primärschlüssel nicht automatisch in der Datenbank generiert wird. EF hilft Ihnen in letzterem Fall auch nicht, weil ein Kontext den Inhalt der gesamten Datenbanktabelle nicht kennt, sondern nur über die Entitäten, die derzeit an den Kontext gebunden sind. Es ist zwar richtig, dass EF verbietet, zwei Objekte mit demselben Primärschlüssel anzuhängen, aber zwei Objekte mit derselben eindeutigen Schlüsseleinschränkung erlaubt. Dies schützt Sie jedoch nicht vollständig vor Verletzungen von Primärschlüsseleinschränkungen, wenn Sie Änderungen an der Datenbank speichern.

Im unwahrscheinlichen Fall, dass zwischen der Any Prüfung und SaveChanges ein anderer Benutzer einen Datensatz mit dem gleichen Wert eingegeben hat, würde ich die auftretenden Ausnahme nicht für möglich halten zu handhaben und sagen Sie dem Benutzer „Ein erwarteter Fehler aufgetreten, bitte versuchen Sie es nochmal...". Wenn der Benutzer es erneut versucht, findet die Überprüfung erneut statt und er erhält die nützlichere Nachricht, um den Eingabewert vom obigen Code zu ändern.

Die Ausnahme, die für solche eindeutigen Schlüsseleinschränkungen oder Primärschlüsseleinschränkungen zurückgegeben wird, ist eine allgemeine DbUpdateException und eine der inneren Ausnahmen ist eine SqlException, die als eine ihrer Eigenschaften einen SQL Server-Fehlercode enthält. Alle anderen Details können nur in der Ausnahmebedingungsnachricht "Verletzung der UNIQUE KEY-Einschränkung IX_SomeUniqueProperty_Index ..." oder ähnlich gefunden werden. Wenn Sie erwarten, dass der Benutzer diese Informationen versteht und entsprechend darauf reagiert, können Sie sie anzeigen. Andernfalls könnten Sie diese Nachricht für einen Administrator oder Entwickler protokollieren, um nach möglichen Fehlern oder anderen Problemen zu suchen.

+0

So, da ich Stapelupdates mache, würde dies erfordern, aktualisierte/hinzugefügte Datensätze in Kunden zu finden, und jeden Datensatz durchlaufen, um zu überprüfen, ob es einen vorhandenen Datensatz mit demselben Wert gibt. Ich bin mir nicht ganz sicher, wie sich das auf die Leistung auswirken wird, wenn mehr als 10 Datensätze geändert werden. Oder in diesem Fall ist es besser, nur eine Ausnahme zu fangen? Die Nachricht muss lokalisiert werden, also scheint es, dass ich eine Prozedur erstellen muss, die eine Nachrichtensuche nach IX_SomeUniqueProperty durchführt, da die Nachricht auch auf Französisch sein kann, wenn OS Französisch ist (wenn ich mich nicht irre), und ich kann nicht abhängen auf "Violation of ...." – Goran

+0

@Goran: Ich verstehe, aber ich würde immer noch eine Abfrage auf Existenz überprüfen. Wenn Sie auch * update * müssen, wie Sie sagen, nicht nur einfügen, müssen Sie nicht für die Entität in der Datenbank trotzdem abfragen? Sie können sich nicht zwischen dem Aktualisieren und Einfügen entscheiden, ohne zu wissen, ob sich die Entität bereits in der DB befindet oder nicht. – Slauma

+0

Die Entscheidung zwischen Aktualisierung und Einfügen wird von EF selbst getroffen.Jede Entität, die ich der Customers-Sammlung hinzugefügt habe, wird als neuer Datensatz betrachtet. Datensätze mit bereits zugewiesener PK werden aktualisiert. Was ich zu beachten habe, ist der Fall, in dem ein Benutzer im Netzwerk einen Datensatz hinzugefügt hat (die Daten des Clients sind in den meisten Fällen nicht mit den Datenbankdaten auf dem neuesten Stand, da dies eine ständige Neusynchronisierung erfordern würde), so dass zwischen den letzten 15 Minuten liegen könnten Daten laden und Änderungen speichern aufrufen. Aus diesem Grund kann ich nicht nur von den Daten abhängen, die auf dem Client zwischengespeichert werden, um zu überprüfen, ob es eindeutige (oder andere) Einschränkungen gibt. – Goran

Verwandte Themen