Folgendes Code-Beispiel zeigt, wie man den Fehler Failed executing DbCommand Update in Asp.Net Core und EF Entity Framework lösen kann.
Aufgabe: meine Asp.Net Core 2 MVC Anwendung hängt sich regelmässig auf, wenn ein Datensatz geschrieben werden soll.
Dabei handelt es sich um einen einfachen Zähler, der die Webseiten zugriffe erhöht.
Die Fehlermeldung in der Log-Datei der Asp Core Anwendung lautet:
fail: Microsoft.EntityFrameworkCore.Database.Command[20102] Failed executing DbCommand (45ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30'] .. UPDATE [tbl_Notes] SET .. System.Data.SqlClient.SqlException (0x80131904): Timeout expired. |
Und hierzu kommt auch der Fehler:
fail: Microsoft.EntityFrameworkCore.Update[10000] An exception occurred in the database while saving changes for context type |
Log-Datei der Asp Anwendung
Fehler-Auszug, wo der Code hängen bleibt.
1: Update eines Datensatzes
fail: Microsoft.EntityFrameworkCore.Database.Command[20102] Failed executing DbCommand (45ms) [Parameters=[@p1='?', @p0='?'], CommandType='Text', CommandTimeout='30'] SET NOCOUNT ON; UPDATE [tbl_Notes] SET [sumViews] = @p0 WHERE [IDNote] = @p1; SELECT @@ROWCOUNT; System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): Der Wartevorgang wurde abgebrochen at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__108_0(Task`1 result) |
2.Update eines Datensatzes
Error Number:-2,State:0,Class:11 fail: Microsoft.EntityFrameworkCore.Update[10000] An exception occurred in the database while saving changes for context type 'Readdy.Data.ApplicationDbContext'. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception: Der Wartevorgang wurde abgebrochen |
Auszug zur Fehlerquelle in den Source-Dateien:
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Counter_Logger.<counter_of_View_erhoehen>d__0.MoveNext() in D:\Programmierung\Web\Readdy\Readdy\Readdy\_classes\Counter_Logger.cs:line 21 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Readdy.Controllers.NotesController.<Details>d__6.MoveNext() in D:\Programmierung\Web\Readdy\Readdy\Readdy\Controllers\NotesController.cs:line 322 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() |
Lösung:
Man kann einfache Speicher-Vorgänge mit AcceptAllChanges erzwingen.
Hierzu muss man den Save-Parameter: AcceptAllChanges in Entity Framework auf True setzen
await EF_Model.dbContext.SaveChangesAsync(true); |
C# Code-Beispiel mit Asp.Net Core 2 und Entity Framework.
Erläuterung.
Während die Methode Daten abholt, und ändert, kann es sein dass der Datensatz von einer anderen Seite geöffnet wird.
Deshalb reicht bei einfachen Zählern und nicht redundanden Loggern das einfache Speichern ohne Transaction-Prüfung
public static async Task<int?> counter_of_View_erhoehen(long IDUser, long IDNote = 0) { //-------------< logViewCounter_erhoehen() >------------- //< Sum ViewLogs > NoteModel note = await EF_Model.dbContext.tbl_Notes.SingleOrDefaultAsync(m => m.IDNote == IDNote); if (note == null) return 0;
if (note.sumViews == null) note.sumViews = 0; note.sumViews += 1; await EF_Model.dbContext.SaveChangesAsync(true); //</ Sum ViewLogs >
return note.sumViews; //-------------</ logViewCounter_erhoehen() >------------- } |
Screenshot
IM Code einfach den Parameter (true) einfügen um das Speichern zu erzwingen