2016-11-02 4 views
0

Ich verwende ASP.Net Core WebAPI.In ASP.Net Core, ist es möglich, JSON-Ergebnisse zu streamen?

Ich habe eine Methode, die 10000 Ergebnisse aus der Datenbank zu einem Zeitpunkt abruft, aber ich stelle fest, dass es dauert 1,17 Sekunden auf "warten" und 0,3 Sekunden für die tatsächliche Übertragung (basierend auf dem Netzwerkdiagramm von Chrome).

Mit den Ergebnissen aus der Datenbank (Postgres) werden durch den DataReader iteriert und in eine Struktur konvertiert, zu einer Liste hinzugefügt und schließlich als JsonResult zurückgegeben.

Ich weiß nicht, was genau für Optionen zu erwarten, aber ich möchte in der Lage sein, so bald wie möglich zurückzukehren, um die Gesamtanforderung niedriger zu machen. Ich mache das zum ersten Mal auf dieser Plattform, also mache ich vielleicht nicht die beste Art und Weise.

[HttpGet("{turbine:int}")] 
    public IActionResult GetBearingTemperature(int turbine) 
    { 
     using (var connection = Database.GetConnection()) 
     { 
      connection.Open(); 

      int? page = GetPage(); 

      var command = connection.CreateCommand(); 

      if (page.HasValue) 
      { 
       command.CommandText = @"select turbine, timestamp, mainbearingtemperature from readings where turbine = :turbine limit 10000 offset :offset;"; 
       command.Parameters.AddWithValue("offset", NpgsqlTypes.NpgsqlDbType.Integer, page.Value * 10000); 
      } else 
      { 
       command.CommandText = @"select turbine, timestamp, mainbearingtemperature from readings where turbine = :turbine limit 10000;"; 
      } 

      command.Parameters.AddWithValue("turbine", NpgsqlTypes.NpgsqlDbType.Integer, 4, turbine);     

      var reader = command.ExecuteReader(); 

      var collection = new List<BearingTemperature>(); 

      if (reader.HasRows) 
      { 
       var bt = new BearingTemperature(); 

       while (reader.Read()) 
       {       
        bt.Time = reader.GetDateTime(1); 
        bt.Turbine = reader.GetInt32(0); 
        bt.Value = reader.GetDouble(2); 

        collection.Add(bt); 
       } 

       return new JsonResult(collection); 
      } 
      else 
      { 
       return new EmptyResult(); 
      } 

     } 
    } 

    private int? GetPage() 
    { 
     if (Request.Query.ContainsKey("page")) 
     { 
      return int.Parse(Request.Query["page"]); 
     } 
     else return null; 

    } 

    struct BearingTemperature 
    { 
     public int Turbine; 
     public DateTime Time; 
     public double Value; 
    } 
+1

1.17s zu "warten" und 0.3s für die tatsächliche Übertragung von 10.000 Datensätze scheint ziemlich gut zu mir. Ich vermute, dass die meiste Zeit damit verbracht wird, die SQL-Abfrage auszuführen, und dass das Streaming überhaupt keinen Unterschied macht. –

+0

Ich habe gerade einige Ergebnisse von der Protokollierung: Abfrage ausführen @ 538 Iterating @ 565 Antwort @ 591 Diese Ergebnisse zeigen Millisekunden. Ich glaube, ich verstehe nicht, wo die Verzögerung herkommt - es scheint nicht in der Methode selbst zu sein. Das ist alles auf dem lokalen Host - was verursacht das Warten? –

Antwort

0

Bedenkt man, dass die Datenbank wird die Abfrage auszuführen und die gesamte Ergebnismenge zurückgeben, ist es nicht möglich, dass Sie eine Teil-Ergebnismenge zu streamen (obwohl Sie Streaming-Datenbank für andere Angebote google können). Stattdessen können Sie mithilfe einer mit ajax kombinierten Paging-Methode Segmente des Gesamtergebnissatzes abrufen und sie zusammen auf dem Client zusammensetzen, um die Reaktionsfähigkeit hoch zu halten und die Illusion von Streaming-Abfrageergebnissen zu erzeugen.

Sie werden OFFSET und LIMIT Klauseln aussehen wollen

Auf Ihrem api, würden Sie umfassen Parameter für Offset und Begrenzung der Client zu ermöglichen, durch zu treten und die Ergebnismenge in beliebig großen Brocken abrufen es will , Sie können damit spielen, um zu bestimmen, was gut genug reagiert. Dann benötigen Sie auf Ihrem Client eine Schleife über einen AJAX-Aufruf an Ihre API, wahrscheinlich mit jQuery, und führen eine Schleife nach der Seite durch, wobei die Ergebnisse der gebundenen Sammlung auf dem Client hinzugefügt oder ui-Elemente oder was auch immer bis zu den Ergebnissen erstellt werden komm zurück leer.

Alternativ, wenn das Anzeigen der gesamten 10k-Datensätze auf einmal nicht erforderlich ist, können Sie einfach die Ergebnisse pagen und eine Schnittstelle bereitstellen, um die Seiten zu durchlaufen. Eine, die ich für einen solchen Zweck verwendet habe, ist von Sakura auf Git Hub: PagedList

+0

Mein SQL verwendet bereits OFFSET und LIMIT. Wie ich meine API eingerichtet habe, funktioniert es mit/api/mbt/{id} mit einem Abfrageabschnitt, der? Page = {num} hätte, wobei num am Ende mit 10000 multipliziert würde. Schließlich wird das Frontend Verwenden Sie AJAX, und wahrscheinlich Aggregationen - wenn es nicht möglich war, sie in der Datenbank zu tun. –

+0

Ah, ich sehe - Scrollen nicht vorher auf Ihrem sql. Nun, das sind die Grenzen. Das Warten ist genau die Zeit, die für die Ausführung des SQL benötigt wird. Übertragen Sie die Daten von SQL Server auf Ihren Controller, durchlaufen Sie die Ergebnisse und erstellen Sie die Rückgabe. Also, wenn Sie diese Zeit verkürzen möchten, können Sie die LIMIT reduzieren und kleinere Blöcke zwischen Controller und Browser übergeben. Der clientseitige Code zum Steuern der zurückkommenden Daten befindet sich dort, wo die Kontrolle ist. Schauen Sie sich alternativ 'PushStreamContent' an: https://weblogs.asp.net/andresv/asynchronous-streaming-in-asp-net-webapi – Erikest

Verwandte Themen