2010-07-26 3 views
0

Sur mon application Web, je charge une page qui peut charger jusqu'à 8 000 lignes ou plus dans un tableau, chaque ligne ayant sa propre liste déroulante. Ce premier processus s'avère extrêmement inefficace mais on m'a demandé de le faire comme ça. Le code de chargement des lignes est le suivant:Accélérer le chargement de la page et le traitement de l'information

<tbody> 
     <% var i = 0; 



      foreach (var row in Model) 
      { 
       var comp = "ok"; 
       if (row.LidExpected != (string.IsNullOrEmpty(row.LidObtained) ? null : row.LidObtained) || row.QuantityExpected != row.QuantityObtained) 
       { 
        comp = "ko"; 
       } 
       %> 
     <tr class="child_row <%= comp %>"> 
      <input type="hidden" name="Goods.index" value="<%= i %>" /> 
      <td class="field <%= InventoryGoods.Metadata.Gid.CssClass %>"> 
       <%-- <%= Html.Encode(row.Gid) %>--%> 
       <%--http://tecnicos.urbanos.com/Goods/Details/... --%> 
       <%= Html.ActionLink(row.Gid, "Details", "Goods", new {id = row.Gid}, null) %> 
       <%= Html.Hidden(String.Format("Record[{0}].Gid", i), row.Gid) %> 
      </td> 
      <td class="field <%= InventoryGoods.Metadata.LidExpected.CssClass %>"> 
       <%= Html.Encode(row.LidExpected) %> 
       <%= Html.Hidden(string.Format("Record[{0}].LidExpected", i), row.LidExpected)%> 
      </td> 
      <td class="fieldRight <%= InventoryGoods.Metadata.QuantityExpected.CssClass %>"> 
       <%= Html.Encode(row.QuantityExpected) %> 
       <%= Html.Hidden(string.Format("Record[{0}].QuantityExpected", i), row.QuantityExpected)%> 
      </td> 
      <td class="field <%= InventoryGoods.Metadata.LidObtained.CssClass %>"> 
       <%= Html.Encode(row.LidObtained) %> 
       <%= Html.Hidden(string.Format("Record[{0}].LidObtained", i), row.LidObtained)%> 
      </td> 
      <td class="fieldRight <%= InventoryGoods.Metadata.QuantityObtained.CssClass %>"> 
       <%= Html.Encode(row.QuantityObtained) %> 
       <%= Html.Hidden(string.Format("Record[{0}].QuantityObtained", i), row.QuantityObtained)%> 
      </td> 
      <%if (int.Parse(state.ToString()) == (int)InventoryStateEnum.Closed || int.Parse(state.ToString()) == (int)InventoryStateEnum.Verified) 
       { %> 
      <td class="field <%= InventoryGoods.Metadata.Action.CssClass %>"> 
       <%       
        switch (row.Action) 
        { 
         case (int)InventoryGoodsActionEnum.AdjustQuantity: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 
         new SelectListItem { Text= "Ajustar Quantidade", Value= ((int)InventoryGoodsActionEnum.AdjustQuantity).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantity == row.Action ? true : false},       
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
         <%  break; 
         case (int)InventoryGoodsActionEnum.AdjustLocation: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 

         new SelectListItem { Text= "Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocation == row.Action ? true : false},       
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
          <% break; 
         case (int)InventoryGoodsActionEnum.AdjustStockType: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        {       
         new SelectListItem { Text= "Ajustar Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustStockType == row.Action ? true : false},       
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
         <% break; 
         case (int)InventoryGoodsActionEnum.AdjustQuantityLocation: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 
         new SelectListItem { Text= "Ajustar Quantidade", Value= ((int)InventoryGoodsActionEnum.AdjustQuantity).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantity == row.Action ? true : false}, 
         new SelectListItem { Text= "Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocation == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Quantidade e Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustQuantityLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantityLocation == row.Action ? true : false},             
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
          <% break; 
         case (int)InventoryGoodsActionEnum.AdjustQuantityStockType: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 
         new SelectListItem { Text= "Ajustar Quantidade", Value= ((int)InventoryGoodsActionEnum.AdjustQuantity).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantity == row.Action ? true : false},       
         new SelectListItem { Text= "Ajustar Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustStockType == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Quantidade e Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustQuantityStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantityStockType == row.Action ? true : false},       
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
         <% break; 
         case (int)InventoryGoodsActionEnum.AdjustLocationStockType: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 

         new SelectListItem { Text= "Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocation == row.Action ? true : false},       
         new SelectListItem { Text= "Ajustar Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustStockType == row.Action ? true : false},       
         new SelectListItem { Text= "Ajustar Tipo de Stock e Relocalizar", Value = ((int)InventoryGoodsActionEnum.AdjustLocationStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocationStockType == row.Action ? true : false},       
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
         <% break; 
         case (int)InventoryGoodsActionEnum.AdjustQuantityLocationStockType: %> 
          <%= Html.DropDownList(String.Format("Record[{0}].Action", i), new[] 
        { 
         new SelectListItem { Text= "Ajustar Quantidade", Value= ((int)InventoryGoodsActionEnum.AdjustQuantity).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantity == row.Action ? true : false}, 
         new SelectListItem { Text= "Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocation == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Quantidade e Relocalizar", Value= ((int)InventoryGoodsActionEnum.AdjustQuantityLocation).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantityLocation == row.Action ? true : false},       
         new SelectListItem { Text= "Ajustar Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustStockType == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Quantidade e Tipo de Stock", Value = ((int)InventoryGoodsActionEnum.AdjustQuantityStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantityStockType == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Tipo de Stock e Relocalizar", Value = ((int)InventoryGoodsActionEnum.AdjustLocationStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustLocationStockType == row.Action ? true : false}, 
         new SelectListItem { Text= "Ajustar Quantidade, Tipo de Stock e Relocalizar", Value = ((int)InventoryGoodsActionEnum.AdjustQuantityLocationStockType).ToString(), Selected= (int)InventoryGoodsActionEnum.AdjustQuantityLocationStockType == row.Action ? true : false}, 
         new SelectListItem { Text= "Ignorar", Value= ((int)InventoryGoodsActionEnum.Ignore).ToString(), Selected= (int)InventoryGoodsActionEnum.Ignore == row.Action ? true : false}, 
        })%> 
         <% break; 
        } 


       %> 
       <%= Html.Hidden(string.Format("db_Action[{0}]", i), row.Action)%> 
      </td> 
      <td> 
       <a title="Apagar Evento" id="delete_Event" class="ui-widget ui-state-default ui-icon ui-icon-trash"> 
       </a> 
      </td> 
      <td class="field <%= InventoryGoods.Metadata.ActionOn.CssClass %>" id="dateCell"> 
       <span id="ActionOn_<%= i %>"> 
        <%= Html.Encode(row.ActionOn.HasValue ? Html.FormatDateTime(row.ActionOn.Value) : Html.Encode(""))%></span> 
       <%= Html.Hidden(String.Format("Record[{0}].ActionOn", i), row.ActionOn.HasValue ? row.ActionOn.Value : new DateTime())%> 
      </td> 
      <% } %> 
      <%= Html.Hidden("lineVal", i) %> 
      <% i++; 
      } %> 
     </tr> 
    </tbody> 

C'est donc la racine de tous les problèmes. Le prochain problème est lorsque j'ai besoin de renvoyer ces données au serveur, ce qui, bien sûr, prendra beaucoup de temps aussi. Je ne connais aucun moyen de le rendre plus rapide, car il faut environ 8 ou 9 minutes pour renvoyer 9 000 lignes au serveur.

Les problèmes persistent lors de l'utilisation de ces lignes pour une mise à jour par lots, comme suit:

public void UpdateInventoryGoods(List<InventoryGoods> list, int id) 
     { 
      //int index = 0; 

      var query = from inventoryGoods in context.InventoryGoods 
         where inventoryGoods.ParentId == id 
         select inventoryGoods; 

      List<InventoryGoods> goodsList = query.ToList(); 
      var memmoryInventoryGoodsEvent = context.InventoryGoodsEvents.ToList();//obter apenas o do Id 

      using (var scope = new TransactionScope()) 
      { 
       var events = from g in context.GoodsEvent 
          select g; 
       List<GoodsEvent> goodsEventList = events.ToList(); 

       foreach (InventoryGoods i in list) 
       { 
        foreach (InventoryGoods e in goodsList) 
        { 
         //if (index == 30) 
         //{ 
         // index = 0; 
         // context.SubmitChanges(); 
         //} 
         var eventId = getEventId(e.Id, memmoryInventoryGoodsEvent); 
         if (e.Gid == i.Gid && !eventId.HasValue && !e.ActionOn.HasValue) 
         { 
          e.Action = i.Action; 

         } 
         else if ((e.Gid == i.Gid && eventId.HasValue) && (e.Action != i.Action || i.ActionOn == DateTime.MinValue)) 
         { 
          e.Action = i.Action; 
          e.ActionOn = null; 



          var inventoryGoodsEventsList = memmoryInventoryGoodsEvent.Where(x => x.InventoryGood == e.Id); 





          foreach (InventoryGoodsEvents goodsEvent in inventoryGoodsEventsList) 
          { 
           context.InventoryGoodsEvents.DeleteOnSubmit(goodsEvent); 

           foreach (GoodsEvent ge in goodsEventList) 
           { 
            if (ge.Id == goodsEvent.EventId) 
            { 
             ge.IsDeleted = true; 
             ge.DeletedOn = DateTime.Now; 
             ge.DeletedBy = System.Web.HttpContext.Current.User.Identity.Name; 
            } 
           } 
          } 




         } 
         //++index; 
        } 
       } 
       context.SubmitChanges(); 
       scope.Complete(); 
      } 

     } 

    public int? getEventId(int InventoryGood,List<InventoryGoodsEvents> memmoryList) 
     { 
      //var firstinventoryGoodsEvents = context.InventoryGoodsEvents.Where(i => i.InventoryGood == InventoryGood).FirstOrDefault(); 
      var firstinventoryGoodsEvents = memmoryList.Where(i => i.InventoryGood == InventoryGood).FirstOrDefault(); 

      if (firstinventoryGoodsEvents != null && firstinventoryGoodsEvents.InventoryGood > 0) 
      { 
       return firstinventoryGoodsEvents.InventoryGood; 

      } 
      else 
      { 
       return null; 
      } 
     } 

Les i et les variables e dans l'itération deux foreach ci-dessus signifie les lignes que j'ai obtenu de la vue et les lignes la base de données. Je les lance l'un contre l'autre pour trouver des différences, et s'il y a des différences, mettez-les à jour. Mais tous ces processus se révèlent trop lent et j'ai vraiment besoin d'améliorer cela rapidement. Spécialement le double pour chaque itération pour lequel je ne peux pas trouver une meilleure solution.

Alors, pourriez-vous m'aider?

EDIT: Je fixe au moins la méthode de mise à jour par l'utilisation de dictionnaires et d'échapper aux doubles itérations foreach que je faisais dans mon code précédent comme ceci:

public void UpdateInventoryGoods(List<InventoryGoods> list, int id) 
    { 
     //int index = 0; 

     var query = from inventoryGoods in context.InventoryGoods 
        where inventoryGoods.ParentId == id 
        select inventoryGoods; 

     Dictionary<string, InventoryGoods> goodsDictionary = query.ToDictionary(p => p.Gid); 
     var memmoryInventoryGoodsEvent = (from c in context.InventoryGoodsEvents 
             join a in context.InventoryGoods on c.InventoryGood equals a.Id 
             where a.ParentId == id 
             select c).ToList();//obter apenas o do Id 

     using (var scope = new TransactionScope()) 
     { 
      var events = from g in context.GoodsEvent 
         select g; 

      Dictionary<int, GoodsEvent> goodsEventDictionary = events.ToDictionary(p => p.Id); 

      //List<GoodsEvent> goodsEventList = events.ToList(); 

      foreach (InventoryGoods i in list) 
      { 

       var eventId = getEventId(i.Id, memmoryInventoryGoodsEvent); 

       var objectToUpdate = goodsDictionary[i.Gid]; 


       if (!eventId.HasValue && !objectToUpdate.ActionOn.HasValue) 
       { 
        objectToUpdate.ActionOn = i.ActionOn; 
        continue; 
       } 
       else if (eventId.HasValue && objectToUpdate.Action != i.Action || i.ActionOn == DateTime.MinValue) 
       { 
        objectToUpdate.Action = i.Action; 
        objectToUpdate.ActionOn = null; 

        var inventoryGoodsEventsList = memmoryInventoryGoodsEvent.Where(x => x.InventoryGood == objectToUpdate.Id); 

        foreach (InventoryGoodsEvents goodsEvent in inventoryGoodsEventsList) 
        { 
         context.InventoryGoodsEvents.DeleteOnSubmit(goodsEvent); 

         var eventToUpdate = goodsEventDictionary[goodsEvent.EventId]; 

           eventToUpdate.IsDeleted = true; 
           eventToUpdate.DeletedOn = DateTime.Now; 
           eventToUpdate.DeletedBy = System.Web.HttpContext.Current.User.Identity.Name;        
        } 

       } 
      } 
      context.SubmitChanges(); 
      scope.Complete(); 
     } 

    } 
+0

Je serais ravi de faire la liste des informations mais je ne peux pas le faire car ce sont mes commandes. L'information doit être affichée tout à la fois ... Je sais que ce n'est pas conseillé, mais je dois au moins rendre le processus un peu moins douloureux ... – Hallaghan

+0

Bonne chance avec ça. Les navigateurs commencent à barfader lorsqu'il y a trop d'éléments DOM. Ce n'est pas parce que la direction l'exige que c'est faisable. http://developer.yahoo.com/performance/rules.html#min_dom –

+0

C'est vrai ... mais peu importe ce que j'ai dit, ce sont les exigences, je ne peux rien faire d'autre que de les respecter. Tout ce que vous pouvez dire qui vous aidera, j'apprécie. Même si vous aidez juste à la double foreach ... – Hallaghan

Répondre

5

Deux options:

  1. Convaincre le client qui est nécessaire ou la pagination des performances en souffriront. Montrez-lui comment d'autres sites bien établis le font.
  2. Utilisez AJAX. Chargez uniquement ce qui peut être vu sur l'écran, choisissez un jQuery scroll plugin et lorsque l'utilisateur fait défiler charger la pièce manquante avec AJAX. Un peu comme Google Images. Vous pouvez également essayer quelques out of the box controls pour éviter le levage de charges lourdes.

Quelle que soit l'option choisie, réparez la soupe que la vue représente actuellement en utilisant des aides.

2

page votre liste. Personne ne peut traiter 8000 lignes à la fois de toute façon. Faites défiler votre liste, fournissez des filtres pour aider vos utilisateurs à trouver des informations et réduisez de beaucoup la quantité de données envoyées.

+4

En plus de cela, consultez votre liste. Et peut-être envisager la pagination aussi bien. –

1

8000 lignes? Vous devriez abandonner cette idée et mettre en place une sorte de pagination. Quelle que soit l'application, afficher 8000 lignes à un utilisateur est inutile. J'utilise mvccontrib grid qui a la capacité de pagination.

0

Ne le faites pas. Aucun navigateur ne va aimer rendre autant d'informations même si vous pouvez obtenir votre serveur pour l'envoyer rapidement. Tout navigateur affichant autant de lignes va fonctionner très lentement sur le client, le défilement sera saccadé et il sera généralement inutilisable. Je conseillerais soit de paginer l'information ou encore mieux filtrer l'information pour montrer seulement ce qui intéresse l'utilisateur, il n'y a aucun moyen qu'un utilisateur soit intéressé par autant de données à la fois.

+0

S'il vous plaît lire ci-dessus comme pour les exigences de mon bureau ... – Hallaghan

0

Une option qui pourrait aider est de rendre les éléments de données pour les listes déroulantes une seule fois pour chaque type de liste déroulante, au format json sur la page.puis créez et remplissez tous les ddl sélectionnés sur le client en utilisant javascript. il sauvegardera tous les transferts de données redondants excessifs pour chaque ligne rendue. il vous suffit de stocker la valeur qui sera sélectionnée dans chaque ligne lorsque vous générez la sélection. c'est juste une idée que je n'ai pas essayée, ceci pourrait mener au client attendant juste le javascript pour faire sa chose aussi bien.

également, pour la mise à jour des données, est ajax une possibilité et appelez juste pour chaque liste déroulante qui est modifiée juste comme le changement se produit?

+0

Cela ne peut pas être fait parce que les modifications ne sont définitives que lorsque l'utilisateur clique sur le bouton Enregistrer. – Hallaghan

0

La première question qui vient à moi est que où est le code lent?

Sur le temps de traitement du serveur, la transmission réseau ou l'heure de rendu dans le navigateur?

Dans certains cas, un gros HTML TABLE est trop lent sur IE (même IE8). Utilisez CSS "table-layout: fixed" pourrait aider à ce sujet.

Questions connexes