none
EF TTL in Entity und Insert-Konzept

    Frage

  • Guten Abend,

    ich habe eine ASP.NET Core WebAPI, welche mit EF-CF arbeitet. Diese WebAPI wird z.B. durch einen UWP-Client verwendet. Jetzt habe ich eine konzeptionelle Frage zu einem Insert:
    Ich habe eine Parent Entity, welche jeweils nur eine bestimmte Anzahl an Child-Entities haben darf. Wie kann ich nun sicherstellen, dass wenn ich also mit EF eine neue Parent-Entity erstelle, und dann die Childs hinzufüge, kein anderer DBContext gerade .savechanges() gegen die Datenbank fährt, und somit im Endeffekt mehr als die erlaubte Anzahl an Child-Entities geinserted werden?

    Eine anderes Problem, wozu mir keine mir wirklich elegant erscheinende Lösung eingefallen ist, ist dass ich für die o.g. Parent-Entity eine Art TTL Wert festlegen können muss, welcher dafür sorgt, dass dieser Datensatz gelöscht wird, sofern er zu alt ist. Der konkrete Grund dafür ist, dass User A die Parent-Entity sozusagen reservieren können soll, sobald er eine bestimmte Aktion über einen Client ausführt. Stürzt dann der Client ab, oder wird das Fenster einfach geschlossen, so wird der TTL Wert vom Client nicht mehr weiter in die Zukunft gesetzt, und die Reservierung ist wieder aufgehoben.
    Vom Konzept her ist mir dies so eingefallen, aber ich wäre für andere, elegantere Vorschläge sehr dankbar, da ich mir nicht denken kann, dass das der einzige Weg ist, das zu lösen.

    Mit freundlichen Grüßen,

    Bodenseecoder



    Donnerstag, 25. Januar 2018 19:38

Alle Antworten

  • Hi Bodenseecoder,

    grundlegend handelt es sich da ja um ein Concurreny Problem [1].

    Was aber nicht nur einen Datensatz angeht sondern die ganze Tabelle.

    Grundlegend sollte es funktionieren, in einer Transaktion[2] mit einem Select zu schauen ob noch ein Datensatz angelegt werden darf und ihn dann in der Transaktion anzulegen.  Schau dir da aber auch mal das Isolations Level an. Ich denke nicht das die ganze Tabelle automatisch einen (Read) Lock erhält.

    Zu 2. einfach eine Spalte mit Zeitstempel erstellen und dann beim Lesen/oder Schreiben ein Delete absetzen bei dem alle Datensätze gelöscht werden die älter als X sind.

    MFG Palin

    [1]Handling Concurrency with the Entity Framework 6 in an ASP.NET MVC 5 Application (10 of 12)

    [2]Entity Framework Working with Transactions (EF6 Onwards)

    Freitag, 26. Januar 2018 16:12
  • Guten Abend,

    vielen Dank für Ihre Antwort. Würde als Isolation-Level nicht eigentlich sogar ReadCommited reichen? Das müsste meiner Meinung nach eigentlich dafür sorgen, dass wenn Task 1 die Query absetzt, die ausliest, wie viele Child-Entities in der Datenbank vorhanden sind, und den INSERT startet, Task zwei warten muss, bis ein Commit ausgeführt wurde, oder?

    Mit freundlichen Grüßen,

    Bodenseecoder

    Donnerstag, 1. Februar 2018 17:01
  • Ich bin mir da nicht wirklich sicher.

    Grundlegend, muss aber der 2 eigentlich die ganze Zeit warten. Sonst lesen beide fast gleichzeitig die Anzahl der Datensätze. Es kommt heraus, das noch einer eingefügt werden kann. Der eine Startet mit seinem Insert, der andere Wartet dann solange und fügt dann seinen Datensatz ein.    

    Und wenn ich mich da nicht vertue wartet ReadCommited nur bis Änderungen gespeichert sind. Gleichzeitiges lesen ist glaube ich noch möglich. 

    Donnerstag, 1. Februar 2018 17:26
  • Guten Abend,

    da haben Sie recht. Welches Isolation-Level würden Sie vorschlagen? Ich habe ehrlichgesagt eine Abneigung gegen ein zu hohes Isolation-Level, da man dann sehr schnell in den Deadlock-Bereich rutschen kann.

    Mit freundlichen Grüßen,

    Bodenseecoder

    Donnerstag, 1. Februar 2018 17:54
  • Ein Deadlock entsteht ja meist wenn eine Transaktion (T1) auf Tabelle 1 und dann auf Tabelle 2 zugreifen, wärend eine zweite genau den Umgelagerten zugriff macht.  T1 wartet dann das T2 die Tabelle 2 freigibt und T2 darauf das T1 die Tabelle 1 freigibt.

    Ich glaube das hast du hier nicht vor.

    Welches Isolations Level du brauchst wusste ich jetzt nicht und hab mal gegoogled. Dabei hab ich die Antwort für EF gefunden. (Bitte drauf achten die 1. Antwort ist nicht die richtige.

    https://stackoverflow.com/questions/13404061/how-can-i-lock-a-table-on-read-using-entity-framework

    p.s.

    Du kannst gerne das du verwenden, ist hier auch im Forum allgemein üblich.

     
    Freitag, 2. Februar 2018 16:13