Récemment, je travaillais sur un code particulièrement complexe qui nécessitait de nombreuses manipulations de données, des regroupements, des tris, etc. et j'ai fait une découverte qui, je l'espère, pourra s'avérer utile pour d'autres développeurs.
En général, lorsque je tire des données d'Acumatica, je suis à l'aise pour tirer des données dans des objets PXResultSet et parcourir les résultats dans une boucle Foreach. Ce modèle est généralement suffisant pour la plupart des tâches. La nouvelle tâche, cependant, nécessitait un traitement important des données plutôt qu'une simple énumération dans la liste. De plus, les performances étant un problème, je voulais minimiser le nombre de fois où je me rendais à la couche de données. Pour ces deux raisons, je voulais que mes données soient indépendantes du cache. Ce que je devais faire, c'était rassembler les données dans un objet IEnumerable, puis les parcourir en boucle, les filtrer, les copier et les manipuler au moyen d'opérations LINQ . Au départ, j'ai eu du mal à intégrer les PXResultSets dans une liste. Je n'étais pas en mesure de le traduire directement dans la liste dont j'avais besoin. Puis j'ai découvert ce qui suit dans le code source.
Var ListofLines = SelectFrom<SOShipLine>.View.Select(this).RowCast<SOShipLine>().ToList();
L'appel RowCast refactorise le PXResultSet en une liste d'objets que vous transmettez à l'appel. Si vous n'êtes pas familier avec cette technique, c'est le bon moment pour rafraîchir votre nomenclature LINQ C#. J'ai constaté que la manipulation des données dans la couche d'application constituait un gain d'efficacité important en termes d'exécution des tâches de programmation et d'amélioration des performances du système. Je trouve deux scénarios courants dans mon code où ce modèle peut apporter des avantages.
Scénario 1 : Prédicats BQL compliqués
Plutôt que de formuler des prédicats BQL compliqués qui groupent par, additionnent, calculent, etc., je déverse un ensemble de données dans une liste et je le manipule via LINQ. Cette méthode est particulièrement utile si vous recherchez des données plusieurs fois pour le même CED. Elle est certainement plus lisible qu'une longue déclaration BQL. Dans le code ci-dessous, la méthode I est un modèle typique tiré de la source Acumatica. La méthode II est une version qui extrait les données avec une clause Where mais laisse le regroupement à la couche applicative. L'avantage ici est que j'ai pu facilement obtenir un compte distinct et que je peux par la suite me référer facilement aux données originales non groupées. Il est également possible que des gains de performance soient réalisés en fonction de la charge du système et de l'architecture de l'instance particulière d'Acumatica.
GIST : https://gist.github.com/patrick711/bea38c39e1324c20cae5c56cddba6e9f
Deuxième scénario : ensembles de données
Je pense que lorsque votre code devient complexe, il est important de considérer les besoins en données de l'ensemble du code d'un point de vue descendant. Lorsque l'on code des tâches compliquées, il est facile de se perdre dans les méandres et de se retrouver à interroger le même DAC plusieurs fois pour accomplir des tâches distinctes. Cela peut être particulièrement vrai si vous êtes doué pour écrire des blocs de code modulaires. L'une des façons les plus simples de repérer ce problème est de penser à la mise à jour des boucles imbriquées. Si vous avez une boucle imbriquée qui extrait des données, un Foreach typique avec un PXSelect, elle déclenchera le PXSelect chaque fois que la boucle supérieure itère. Plutôt que d'itérer un appel à la couche de données à chaque fois, vous pouvez envisager d'extraire un ensemble de données plus important une fois au-dessus de la boucle et de filtrer l'ensemble à chaque itération de la boucle. Dans la méthode II ci-dessous, j'extrais un ensemble de comptes avec les comptes parents avant le début du bouclage. Mais attendez, me direz-vous, pourquoi ne pas extraire tous les comptes pour les deux boucles ? C'est peut-être une bonne chose, surtout si vous avez besoin de ces données pour d'autres tâches ou si vous avez une bonne idée de l'ensemble de données qui en résultera. Mais cela pourrait aussi entraîner l'extraction d'un ensemble de données inutilement volumineux, ce qui annulerait les gains de performance que vous pourriez réaliser. Comme toujours, il est important de tenir compte de la topologie de vos données.
GIST : https://gist.github.com/patrick711/49a7a0e361f0acb17742f162da16e773
Ces exemples sont présentés comme un moyen de rendre le code plus lisible, d'exploiter les capacités natives du langage C# et, éventuellement, d'améliorer les performances. J'espère que cela vous a été utile, bon codage !