Ist durch das Nutzen einer API sichergestellt, dass die dahinterliegende Datenbank keine 'zeitgleichen' Anfragen bekommt?

  • C# (ASP)
  • (Core) Blazor WebAssembly

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Ist durch das Nutzen einer API sichergestellt, dass die dahinterliegende Datenbank keine 'zeitgleichen' Anfragen bekommt?

    Ist durch das Nutzen einer Web-API sichergestellt, dass die dahinterliegende Datenbank keine 'zeitgleichen' Anfragen bekommt?

    Ich weiß, dass die noSQL LiteDB (Datenbank) die ich nutzen möchte keinen Schutz gegen gleichzeitige Anfragen hat. Es sollte laut Dokumentation nur ein Benutzer zur Zeit mit der Datenbank arbeiten.

    Meine Frage ist nun, wenn ich die DB über die API anspreche wird das seriell abgearbeitet?
    Kann ich davon ausgehen, dass egal wie viele User zeitgleich eine Anfrage an die DB stellen, dass aufgrund der API alle Anfragen 'schön' der Reihe nach abgearbeitet werden?
    Der User hat nie direkten Zugriff auf die DB nur die Server Software. Auf dem Server würde ich einen Singleton-Service erzeugen und jeder DB-Zugriff läuft darüber (also es würde nur eine Instanz auf die DB zugreifen).


    Konkret möchte ich mit folgenden Teilen ein Projekt starten: Blazor-Webassambly-App, .net Maui Blazor-App, Datenbank LiteDB

    Teil 1 Blazor-Webassambly-App BlazorServer und BlazorClient-App inklusive der API. In meinem BlazorServer-Projekt läuft die Datenbank LiteDB (noSQL)
    Teil 2 .net Maui Blazor-App API Konsument läuft auf Android
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „nogood“ ()

    nogood schrieb:

    Ist durch das Nutzen einer Web-API sichergestellt, dass die dahinterliegende Datenbank keine 'zeitgleichen' Anfragen bekommt?
    nein,
    im Gegenteil: Eine Web-Api nimmt Anfragen an wie sie kommen - da ergibt sich selbstverständlich erstmal Nebenläufigkeit.

    Aber steht dir natürlich frei, iwelche Zentral-Funktionalität in einen sequenziellen Ablauf zu kanalisieren.
    Oder mit SyncLock und Konsorten immer nur jeweils einen Thread ranzulassen.
    Lass dich dabei beraten - es schon oft gelöst worden, und es gibt mehrere konkurrierende Technologien dafür, also in dem Bereich ist das Rad glaub fünfmal neu erfunden worden, und du hast nu die Qual der Wahl.
    @ErfinderDesRades Wie sieht es den mit dem Gedanken aus, dass auf dem Server ein Service läuft der als 'Singleton' arbeitet und nur diese Instanz interagiert mit der DB. Würde das dafür sorgen, dass alles der Reihe nach läuft.

    In ASP.net gibt es die Möglichkeit per Dependency Injection einen Service zu starten der als Lifetime Singleton hat. Es gibt die Instanz des Service z.B. 'MyRepo' dann nur einmal. Egal wieviel User mit dem Server verbunden sind (alle User teilen sich dieselbe Instanz/Objekt). Wenn jetzt dieser Service 'MyRepo' so aussehen würde Pseudo-Code Class:

    C#-Quellcode

    1. public class MyRepo
    2. {
    3. public MyItem GetAllItems()
    4. {
    5. return DataBaseCall.GetAll();
    6. }
    7. public void AddItem(MyItem item)
    8. {
    9. DataBaseCall.AddItem(item);
    10. }
    11. //...
    12. }



    Die Anfragen der User würden dann in etwa so aussehen: ​var res = _myRepo.GetGetAllItems();


    Würde dann die DB-Abfragen seriell erfolgen und ich hätte mein Problem gelöst (Useranzahl unter 20)?
    codewars.com Rank: 4 kyu
    Disclaimer: Mit LiteDB direkt habe ich noch nie gearbeitet. Alles Folgende schreibe ich nur anhand der LiteDB Dokumentation.

    nogood schrieb:

    Es sollte laut Dokumentation nur ein Benutzer zur Zeit mit der Datenbank arbeiten.

    Wichtig ist in dem Kontext, was genau ein Benutzer ist. Aus der Sicht von LiteDB ist ein Benutzer kein User im klassischen Sinne, sondern eine geöffnete Verbindung zur Datenbank (bzw. ein Prozess, der mit der DB arbeitet).
    Das Verhalten kommt auch darauf ein, welchen Connection Type du benutzt. Ich vermute Direct - das macht in deinem Fall (1 einziger Service/Prozess, der mit der DB arbeitet) am meisten Sinn. Theoretisch könnten durch Shared aber sogar mehrere Prozesse gleichzeit mit der DB arbeiten.

    nogood schrieb:

    auf dem Server ein Service läuft der als 'Singleton' arbeitet und nur diese Instanz interagiert mit der DB

    Der Gedanke geht in die richtige Richtung. Allerdings würde ich nicht die Repos als Singleton registrieren (zumindest nicht aus diesem Grund), sondern die dahinterliegende DB Verbindung LiteDatabase, die von den Repos gebraucht wird. Dadurch bleibt die Connection offen, solange dein Service läuft. LiteDatabase ist laut Doku threadsicher und sollte sich dementsprechend automatisch darum kümmern, dass parallele Anfragen richtig behandelt werden.

    Das Setup könnte als sein (Achtung, Pseudocode):

    C#-Quellcode

    1. // Startup:
    2. services.AddSingleton(new LiteDatabase("CONNECTION_STRING"));
    3. services.AddTransient<MyRepo>();
    4. class MyRepo {
    5. private readonly LiteDatabase _db;
    6. public MyRepo(LiteDatabase db) {
    7. _db = db;
    8. }
    9. public async Task<Item> GetAll() {
    10. return await _db.SomeMagicToGetAllItems();
    11. }
    12. }


    Je nach Anforderungen geht das auch unendlich viel komplizierter, aber das sollte ein guter Start sein.
    Da du im Bereich WebApi unterwegs bist und offensichtlich auch Dependency-Injection nutzt gehe ich mal davon aus, dass du auch das Entity Framework verwendest. Du registrierst den DbContext als Singleton in der ServiceCollection. Es ist wichtig, dass alle Anfragen auf dem gleichen Context laufen, weil du andernfalls sofort Deadlocks provizierst. Die Repositories werden für gewöhnlich als Transient, seltener auch als Scoped registriert. Arbeitest du mit richtigen Repositories oder direkt auf den DbSets? Deine Methoden in Post #3 lassen leider keine Rückschlüsse zu


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Yanbel“ ()

    Yanbel schrieb:

    Es ist wichtig, dass alle Anfragen auf dem gleichen Context laufen, weil du andernfalls sofort Deadlocks provizierst.
    Ja, und da ist das Rad mehrfach erfunden worden.
    Es gibt Synclock, ManualResetEvent, AutoResetEvent, ManualResetEventSlim, Monitor, ConcurrentCollection, SynchronisizeContext, Semaphore, ... weiteres?
    Klassische Verwendung von SyncLock wird wohl am nächsten liegen, aber ob's nicht effizienteres gibt, weiss ich nicht.
    Ich glaub auch, nicht alles was ich aufgezählt hab ist relevant. jdfs. da fliegt einiges an Konzepten und Ansätzen herum und QualderWahl.
    @ErfinderDesRades jap, da geb ich dir absolut Recht, spielt aber bei WebApis tatsächliche eine untergeordnete Rolle wie ich feststellen musste. Wenn man sich bei der Entwicklung an den .NET-Ansatz von Microsoft hält, braucht man sich um Deadlocks nicht mehr zu kümmern. Ich habe bei mittlerweile 19 API-Projekte (darunter Komplettschnittstellen zwischen Produktinformationssystemen, Lieferantenportal und Webshop zur Warenwirtschaft) bisher keine Probleme in diese Richtung gehabt. Das einzige Projekt bei dem ich bisher tatsächlich solche Probleme hatte, war ein Plugin-basierter Multithreading-Backgroundservice für den Austausch von Daten zwischen mehreren SQL-Servern. Die Contexte wurden Anfangs nicht per DI in die Plugins übergeben, sondern für jedes Plugin wurde ein eigener Context erstellt und die haben sich dann gegenseitig gesperrt.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.