2010-07-20 9 views
0

ok c'est la chose que j'ai en ce moment qui fonctionne assez bien, sauf son un peu lent:Comment charger une classe générique sans boucle

Public Function GetList() As List(Of SalesOrder) 
Try 
    Dim list As New List(Of SalesOrder) 

    Dim ds As DataSet 

    ds = cls.GetSalesOrderList 'CLS is the data access class 


    For i = 0 To ds.Tables(0).Rows.Count - 1 

     Dim row As DataRow = ds.Tables(0).Rows(i) 
     Dim kk As SalesOrder = New SalesOrder() 


     kk.ID = Val(row.Item("id") & "") 
     kk.SalesOrderNo = row.Item("salesorderid") & "" 
     kk.SalesOrderDate = row.Item("OrderDate") & "" 
     kk.CustomerId = Val(row.Item("customerid") & "") 

     list.Add(kk) 

    Next 
    Return list 

    Catch ex As Exception 
     Throw ex 
    End Try 

End Function 

Maintenant, une fois que je commence à récupérer plus de 10000 enregistrements de la table , la boucle prend beaucoup de temps pour charger les valeurs dans la classe générique. Est-il possible que je puisse me débarrasser de la boucle? Puis-je faire quelque chose comme ce qui suit avec la classe générique?

txtSearch.AutoCompleteCustomSource.AddRange(Array. ConvertAll(Of DataRow, String)(BusinessLogic.ToDataTable.ConvertTo(WorkOr derList).Select(), Function(row As DataRow) row("TradeContactName"))) 
+0

Vous pouvez le faire avec LINQ, mais puisque votre code est en VB, je ne vais pas essayer de fournir une réponse. –

+0

envisager d'ajouter le tag VB.Net – mathk

+0

Merci pour votre réponse les gars. Mais je suppose que tant que le code est écrit en .net, il ne devrait pas être question si le code est écrit dans vb.net ou C#. Parce que je suis d'accord avec C# et vb.net. Donc, si vous avez une solution à mon problème, même en C# alors faites le moi savoir. J'apprécierai vraiment. Merci – NomanEagle

Répondre

0

J'aurais pensé que le problème n'était pas de faire une boucle mais avec des volumes de données. Votre méthode de boucle semble traiter chaque bit de données une seule fois, il n'y a donc pas d'écrasement massif de l'efficacité (comme une boucle sur l'ensemble de données une fois et puis de nouveau pour chaque ligne ou ce genre de chose). Toute méthode que vous choisissez est à la fin de la journée d'avoir à parcourir toutes vos données.

Leurs méthodes pourraient être légèrement plus efficaces que les vôtres, mais ils ne vont pas être beaucoup plus, donc je pense. Je regarderais si vous pouvez faire un refactoring pour réduire votre ensemble de données (par exemple le limiter à une certaine période ou similaire) ou si vous pouvez faire n'importe quelle recherche ou agrégation de cette liste dans la base de données plutôt que dans le code. Par exemple, si vous ne faites que sommer les valeurs de cette liste, vous pouvez presque certainement le faire mieux en ayant une procédure stockée qui fera la sommation sur la base de données plutôt que dans le code.

Je sais que cela n'a pas directement répondu à votre question, mais c'est principalement parce que je ne connais pas une méthode plus efficace. J'ai pris la question en demandant l'optimisation en général, mais plutôt que sur la façon de le faire. :)

+0

Merci pour la réponse. Mais je suis sûr que la réponse à ma question est cachée quelque part dans le code suivant.C'est juste que je ne suis pas capable de convertir cette logique dans mon code de classe générique. Le code suivant ajoute des mots-clés dans la zone de texte pour la recherche sans boucle. Les valeurs proviennent de la collection de classes générique (List). txtSearch.AutoCompleteCustomSource.AddRange (tableau ConvertAll (de DataRow, chaîne) (BusinessLogic.ToDataTable.ConvertTo (liste derOist WorkOr) .Select(), fonction (ligne en tant que DataRow) row ("TradeContactName"))) – NomanEagle

0

La conversion de la boucle en un type de construction LINQ n'améliorera pas nécessairement les performances si vous continuez d'énumérer toutes les lignes à la fois. Vous pouvez retourner IEnumerable (Of SalesOrder) si vous n'avez pas besoin de donner au consommateur la possibilité d'ajouter/supprimer de la liste (ce qui semble être le cas), et dans ce cas vous pouvez créer un énumérateur pour gérer ce. De cette façon, l'ensemble de données est chargé en une seule fois, mais les éléments sont uniquement convertis en objets lors de leur énumération, ce qui peut faire partie de votre performance.

Quelque chose comme ceci:

Return ds.Tables(0).Rows.Select(Function(dr As DataRow) Return New SalesOrder ...); 

Mon VB avec LINQ est un peu rouillé, mais quelque chose à cet effet, où le ... est le code pour instancier un nouveau SalesOrder. Cela créera uniquement un nouvel objet SalesOrder lorsque IEnumerable (Of SalesOrder) est énuméré (paresseux, si vous voulez).

+0

oh je vois . Mais je n'ai jamais utilisé IEnumerable. J'ai vérifié le lien suivant mais c'est un peu compliqué. Ma classe est assez simple sans aucune méthode d'ajout/suppression. Btw, en C# ce serait return ds.Tables [0] .Rows.Select (dr => new) http://msdn.microsoft.com/en-zs/library/system.collections.ienumerable.aspx – NomanEagle

+0

SalesOrder (dr)); où vous avez une surcharge de constructeur qui remplit votre objet d'un datarow. Vous pouvez le faire de plusieurs façons, cela dépend de votre style. Et l'instruction Select() est implicitement convertible en IEnumerable (Of T), il suffit donc de définir le type de retour de la méthode sur IEnumerable (Of SalesOrder) si vous utilisez cette méthode - c'est tout. – Paul

+0

Comment select() identifierait quelle propriété de classe générique doit être remplie avec quel champ de dataset? – NomanEagle

0

Hey Paul, tu veux dire quelque chose comme ci-dessous le code

Dim list As New List(Of SalesOrder) 

Dim kk As SalesOrder = New SalesOrder() 

Function DrToOrder(dr as datareader)  
     kk.ID = Val(dr.Item("id") & "") 
     kk.SalesOrderNo = dr.Item("salesorderid") & "" 
     list.Add(kk)  
End function 

Function LoadData()  
     datareader.Rows.Select(DrToOrder)  
End function 

Voulez-vous parler de quelque chose comme code ci-dessus?

+0

Votre formatage est foiré . –