2017-06-21 1 views
0

Ich habe vor kurzem einige Suchfunktionen zu meiner Anwendung hinzugefügt. Es funktioniert gut, aber es gibt ein Element, genannt Folder, das gesucht wird, erfordert, dass ich ein paar Web-Service-Anrufe machen. Ich gebe maximal 100 Elemente gleichzeitig zurück, und wenn alle 100 Elemente speziell diesen Typ aufweisen und jeweils 3 oder 4 Web-Service-Aufrufe erfordern, dauert es bis zu 30 Sekunden, um die Informationen zu erhalten.MVC - Lazy Load 1 String an mehreren Stellen

Das bisschen Information, die ich bekomme, ist ein Path. Die Datei Path entspricht einem Dateipfad auf einem PC, und für jede Ebene wird ein neuer Webservice-Aufruf ausgeführt. Wenn ich den Code entferne, um diesen Pfad für jedes zurückgegebene Element zu erhalten, kann ich die Ergebnisse innerhalb von 2 bis 3 Sekunden mit 100 Ergebnissen an den Benutzer senden. Dies ist auf meiner Entwicklungsmaschine, so hoffe ich ein wenig schneller in der Produktion.

Was ich versuche zu tun, ist die Path für jede Folder, nachdem es auf dem Bildschirm geladen wurde. Auf diese Weise ist die Mehrheit der Informationen bereits vorhanden, damit der Benutzer sie in einer akzeptablen Zeitspanne sehen kann, und die Path lädt eine Sekunde oder zwei später.

Was ich bisher ein Verfahren, in meinem Controller, der die Path als String zurück:

[HttpGet] 
    public string _SearchGetFolderPath(int folderID) 
    { 
     using (SA sa = new SA()) 
     using (IRWS irws = new IRWS(sa.Ticket)) 
     { 
      return irws.getFolderPathfromFolderID(folderID); 
     } 
    } 

Bei dem obigen Verfahren, das SA-Objekt ist eine Benutzeridentität für den Web-Service und die IRWS Objekt ist, wo ich meine Web-Service-Anrufe behalte.

Dann habe ich dies in meiner Sicht:

@*Display Each Returned Result*@ 
     @foreach (var item in Model) 
     { 
      <div class="panel panel-default"> 
       <div class="panel-heading clearfix"> 
        <h3 class="panel-title pull-left">@(item.Name)</h3> 
        <span class="pull-right">@item.AspectType.AspectName</span> 
       </div> 
       <div class="panel-body"> 
        <dl class="dl-horizontal"> 
         @foreach (var value in item.FieldValues) 
         { 
          <dt>@value.FieldName</dt> 
          @*Test if Item is a Folder and Field is Path*@ 
         if (item.AspectType.AspectTypeID == -10 && value.FieldName.Contains("Path")) 
         { 
          /*Folder Path - get path*/ 
          // HERE IS WHERE I WOULD LIKE TO LAZY LOAD THE PATH 
         } 
         else if (false) 
         { 

         } 
         else 
         { 
          <dd>@value.FieldValue</dd> 
          } 

         } 
        </dl> 
       </div> 
      </div> 
      <br /> 
     } 

Ich möchte dies in ähnlicher Weise, wie ein anderer Teil meiner Anwendung funktioniert arbeiten. Jedes Folder hat eine Seite, die mehr Informationen gibt, und ich benutze Telerik für alle meine UI, also lade ich die Folder Kinder in einem Panel Bar (http://demos.telerik.com/aspnet-mvc/panelbar/ajax).

Alle Ideen oder Vorschläge werden sehr geschätzt. Vielen Dank.

Antwort

0

Lazy Loading in wie das Beispiel in irgendeiner Weise zu C# gebacken unten, die helfen können:

public class yourClassName { 
    static object _lock = new object(); 
    static IDictionary<string, string> loadedValues = new Dictionary<string, string>(); 


    private string BuildString(int folderID) { 
     if (!loadedValues.ContainsKey(folderID)) // if we dont have the value 
      using (SA sa = new SA()) 
      using (IRWS irws = new IRWS(sa.Ticket)) 
       lock(this) 
        if (loadedValues.ContainsKey(folderID)) // lets check again (maybe in btween the locks other threads did the job) 
         lock(_lock) 
          return loadedValues[folderID]; 
        else // it looks like we dont have it (now it is populated) 
         loadedValues.Add(folderID, irws.getFolderPathfromFolderID(folderID)); 
     return loadedValues[folderID] 
    } 

    [HttpGet] 
    public string _SearchGetFolderPath(int folderID) 
    { 
     return BuildString(folderID); 
    } 

} 

Lazy Loading von Natur aus für mich, es zu empfehlen, es mir erfordert etwas mehr Logik zu wissen, und warum ist es benutzt.

Als Alternative während Sie in der MVC.net Welt sind, können Sie MVC Caching nutzen, was Ihnen in diesem Fall noch mehr Zeit spart (Controller Methode wird nicht aufgerufen und die Ansicht html/tmplate wird zwischengespeichert) Zeile unterhalb als Attribut Sie Methode

[OutputCache(Duration = 10 /* minutes */, VaryByParam = "folderID")] 

für mehr auf MVC-Caching Links unten

Konzepte und wie es funktioniert
https://msdn.microsoft.com/en-us/library/ff648482.aspx

so finden Sie uns e/optimieren cache
https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/improving-performance-with-output-caching-cs

+0

Das Problem mit dem Zwischenspeichern des Pfades ist, dass der Pfad jederzeit ändern kann. – JohZant

+0

Hinzugefügt das Lazy Laden und Caching basierend auf Ordner-ID Bit, hoffe es hilft :) was Sie suchen, ist nicht faul laden, wenn der Wert ändert (zu denken, dass die Verwendung Anweisung nicht die teuren Zeilen ist aber die "GetFolderPath" ist die teure Zeile) –

+0

Sie haben Recht, dass 'irws.getFolderPathfromFolderID (folderID)' eine Schleife enthält, die die Details für das nächste Kind erhält, bis es einen vollständigen Pfad hat. Vielleicht sollte ich es einfach auf die alte Art und Weise machen ... Ein Knopf für jeden Pfad. Haha. – JohZant