Gael's profileGael Duhamel - SharePoin...PhotosBlogListsMore ![]() | Help |
|
October 26 [Commerce Server] ProductConfiguration / CategoryConfiguration ou les oubliés de Commerce ServerCes derniers temps, j’ai été sollicité sur des problématiques d’expertise Commerce Server qui m’ont permis de me rendre compte que 2 classes fondamentales pour tous développements Commerce Server étaient totalement méconnue, j’ai nommé:
Ces deux classes héritent toutes de la classe Microsoft.CommerceServer.Catalog.CatalogItemConfiguration, et elles sont utilisées pour ne charger que les éléments que vous avez besoin d’utiliser. En effet, il n’est pas rare lorsque vous souhaitez afficher une liste de produits, de ne vouloir afficher que certaines propriétés du produit sans avoir à utiliser ses variants, ses catégories parentes, etc., etc.... D’ailleurs, si vous jetez un œil sur l’API via Reflector, vous vous apercevez que la classe CategoryConfiguration ou ProductConfiguration est instanciée si vous n’en spécifiez aucune (ie, le framework choisit pour vous les choses à charger): Pour illustrer l’importance de ces classes, prenons l’exemple de la récupération d’un produit ou nous n’avons besoin d’afficher que son prix et son descriptif:
Product product = catalogCtx.GetProduct("Adventure Works Catalog", "AW029-03");
exec dbo.ctlg_GetProductProperties @BCName=N'Adventure Works Catalog' ,@fVirtualCatalog=0 ,@oid=30 ,@ProductUID_tmp=N'ProductCode' ,@VariantUID_tmp=N'VariantCode' ,@catalogname=N'Adventure Works Catalog' ,@Language=N'en-US' ,@eJoinType=-1 ,@TargetTableName=N'' ,@SourceJoinKey=N'' ,@TargetJoinKey=N'' ,@Columns_tmp=N'P.BaseCatalogName,CategoryName,P.oid,DefinitionName,IsSearchable,cy_list_price,UseCategoryPricing,i_ClassType,CatalogName,ProductId,OrigProductId,VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,Timestamp,OriginalPrice,LastModified,ParentOId' ,@EnableInventory=1 ,@InventoryServerName=NULL ,@InventoryDatabaseName=NULL ,@FilterOutOfStockProducts=0 ,@FilterBackOrderableProducts=0 ,@filterPreorderedSkus=0 ,@UseThresholdAsFloor=1 ,@TreatmissingAsOutOfStock=0 ,@StockHandling=0 declare @p15 int set @p15=3 exec dbo.ctlg_GetProductVariantProperties @fVirtualCatalog=0 ,@catalogname=N'Adventure Works Catalog' ,@Language=N'en-US' ,@ProductID=N'AW029-03' ,@VariantID=N'' ,@eJoinType=-1 ,@TargetTableName=N'' ,@SourceJoinKey=N'' ,@TargetJoinKey=N'' ,@BuiltInColumnsToReturn=N'BaseCatalogName,CategoryName,OrigCategoryName,P.oid,DefinitionName,IsSearchable,cy_list_price,UseCategoryPricing,i_ClassType,P.CatalogName,ProductId,OrigProductId,VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,Timestamp,OriginalPrice,LastModified,rank,ParentOId' ,@OrderBy=N'[Rank]' ,@StartingRec=1 ,@NumRecords=2147483646 ,@SortAscending=1 ,@RecordCount=@p15 output ,@ProductOID=30 ,@EnableInventory=1 ,@InventoryServerName=default ,@InventoryDatabaseName=default ,@FilterOutOfStockProducts=0 ,@FilterBackOrderableProducts=0 ,@FilterPreorderedSkus=0 ,@UseThresholdAsFloor=1 ,@TreatmissingAsOutOfStock=0 ,@StockHandling=0 ,@VariantUID=N'VariantCode' select @p15
ProductConfiguration pdtConf = new ProductConfiguration(); pdtConf.InventoryOptions = new Microsoft.CommerceServer.Inventory.InventoryOptions(); pdtConf.InventoryOptions.FilterBackorderableSkus = false; pdtConf.InventoryOptions.FilterOutOfStockSkus = false; pdtConf.InventoryOptions.FilterPreorderableSkus = false; pdtConf.LoadAncestorCategories = false; pdtConf.LoadCanonicalCategories = false; pdtConf.LoadParentCategories = false; pdtConf.LoadRelatedCategories = false; pdtConf.LoadRelatedProducts = false; pdtConf.LoadVariants = false; Product product = catalogCtx.GetProduct("Adventure Works Catalog", "AW029-03", "en-US", pdtConf); En apparence , le ProductConfiguration nous a permi d’éviter l’appel à la procédure stockée qui nous remontait les variants. Mais jetez un oeil du côté des statistiques SQL pour vous apercevoir qu’il y a bien plus que cela:
Impressionnant non? :) 3 fois moins d’exécution côté SQL :) Attaquons nous maintenant à la catégorie. C’est là ou les résultats sont les plus impressionnant (si si :))
Category category = catalogCtx.GetCategory("Adventure Works Catalog", "Tents");
CategoryConfiguration catConf = new CategoryConfiguration(); catConf.InventoryOptions = new Microsoft.CommerceServer.Inventory.InventoryOptions(); catConf.InventoryOptions.FilterBackorderableSkus = false; catConf.InventoryOptions.FilterOutOfStockSkus = false; catConf.InventoryOptions.FilterPreorderableSkus = false; catConf.LoadAncestorCategories = false; catConf.LoadCanonicalCategories = false; catConf.LoadParentCategories = false; catConf.LoadRelatedCategories = false; catConf.LoadRelatedProducts = false; Category category = catalogCtx.GetCategory("Adventure Works Catalog", "Tents", "en-US", catConf);
Grâce à la classe CategoryConfiguration correctement configurée, on a évité 2 exécutions de procédure stockée, mais vu côté statistique SQL c’est impressionnant! Jugé plutôt:
Quasiment 5 fois moins d’exécution SQL, pour un même résultat!!!! Vous comprennez donc maintenant pourquoi il est très important de spécifier un CatalogItemConfiguration: il peut changer drastiquement les performances de votre site e-Commerce (et ceci même si vous utilisez le cache). Pour ma part, si vous ne savez pas à l’avance quoi loader (c’est rarement le cas… j’espère ;)), je vous recommande plutôt d’opter pour du lazy loading, c’est à dire de configurer au minima (en gros je mets toutes les options à false) mon GetProduct ou GetCategory et laisse l’API charger les objets dont j’ai besoin. Pour terminer, j’ai mis un petit graphique illustrant mes propos ou je me suis amusé à boucler 50 fois sur une récupération de Produit via un getProduct avec différentes options (pour info le cache était activé): En bleu: ctx.RefreshCache(); //refresh the catalogue cache system for (int i = 0; i < 50; i++) { chrono.Start(); foreach (String pId in Constants.PRODUCTS) { Product p = ctx.GetProduct(Constants.CATALOGNAME, pId, "en-US"); } chrono.Stop(); long spent = chrono.ElapsedMilliseconds; chrono.Reset(); } En rouge: ctx.RefreshCache(); //refresh the catalogue cache systemProductConfiguration pdtConf = new ProductConfiguration(); pdtConf.InventoryOptions = new Microsoft.CommerceServer.Inventory.InventoryOptions(); pdtConf.InventoryOptions.FilterBackorderableSkus = true; pdtConf.InventoryOptions.FilterOutOfStockSkus = true; pdtConf.InventoryOptions.FilterPreorderableSkus = true; pdtConf.InventoryOptions.PropertiesToReturn = propertiesToReturn; pdtConf.LoadAncestorCategories = true; pdtConf.LoadCanonicalCategories = true; pdtConf.LoadParentCategories = true; pdtConf.LoadRelatedCategories = true; pdtConf.LoadRelatedProducts = true; pdtConf.LoadVariants = true; pdtConf.ParentPropertiesToReturn = "*"; pdtConf.Variants.SearchOptions = new CatalogSearchOptions(); pdtConf.Variants.SearchOptions.PropertiesToReturn = "*"; for (int i = 0; i < 50; i++) { chrono.Start(); foreach (String pId in Constants.PRODUCTS) { Product p = ctx.GetProduct(Constants.CATALOGNAME, pId, "en-US", pdtConf); } chrono.Stop(); long spent = chrono.ElapsedMilliseconds; chrono.Reset(); } En vert: ctx.RefreshCache(); //refresh the catalogue cache systemProductConfiguration pdtConf = new ProductConfiguration(); pdtConf.InventoryOptions = new Microsoft.CommerceServer.Inventory.InventoryOptions(); pdtConf.InventoryOptions.FilterBackorderableSkus = false; pdtConf.InventoryOptions.FilterOutOfStockSkus = false; pdtConf.InventoryOptions.FilterPreorderableSkus = false; pdtConf.InventoryOptions.PropertiesToReturn = propertiesToReturn; pdtConf.LoadAncestorCategories = false; pdtConf.LoadCanonicalCategories = false; pdtConf.LoadParentCategories = false; pdtConf.LoadRelatedCategories = false; pdtConf.LoadRelatedProducts = false; pdtConf.LoadVariants = false; pdtConf.ParentPropertiesToReturn = "*"; pdtConf.Variants.SearchOptions = new CatalogSearchOptions(); pdtConf.Variants.SearchOptions.PropertiesToReturn = "*"; for (int i = 0; i < 50; i++) { chrono.Start(); foreach (String pId in Constants.PRODUCTS) { Product p = ctx.GetProduct(Constants.CATALOGNAME, pId, "en-US", pdtConf); } chrono.Stop(); long spent = chrono.ElapsedMilliseconds; chrono.Reset(); } [Commerce Server] Trier les propriétés Commerce Server selon des ordres de tri différentsPour faire suite à une discussion sur le forum Commerce Server: How could i sort by property1 ASC and property2 DESC in a catalog search?, je me suis aperçu qu’une fonctionnalité de base de Commerce Server était mal comprise. En effet, il n’est pas rare sur une liste de produits (ou de catégorie) de vouloir trier le résultat sur plusieurs critères et dans des sens différents tout en gardant la fonctionnalité de paging du CatalogSearch. Ravi proposait pour solutionner cela d’utiliser un dataview. Le problème est que le dataview ne peut trier que sur le résultat de la recherche! Quid donc si vous avez plusieurs pages? Sans compter les piètres performances d’un dataview. Pour solutionner cela, il suffit simplement de mettre le nom de votre propriété entre crochet [] puis de coller à la suite l’ordre du tri ex: CatalogSearch catalogSearch = catalogContext.GetCatalogSearch(); catalogSearch.CatalogNames = "MyCatalog"; catalogSearch.SearchOptions.ClassTypes = CatalogClassTypes.ProductFamilyClass; catalogSearch.SearchOptions.PropertiesToReturn = "ProductId, cy_list_price"; catalogSearch.CategoriesClause = "CategoryName = 'CatId"; catalogSearch.SqlWhereClause = "Display = 'OK'"; catalogSearch.SearchOptions.SortProperty = "[ProductId]ASC, [cy_list_price]DESC"; Attention, il est important qu’il n’y ait pas d’espace entre le crochet fermant et l’ordre de tri. Pour info, notre expert en développement Commerce Server, Anoir, avait déjà écrit un article à ce sujet: Recherche d’un produit avec plusieurs colonnes de tris différenciés sur le blog d’Altima. Technorati Tags: Commerce Server,tri différentié October 24 [TechEd 2009] Rencontrez les experts Commerce ServerJe serais présent du 9 au 13 novembre 2009 à Berlin pour les tech-ed EMEA. Durant cette semaine, vous pourrez me rencontrer ainsi que l’équipe Commerce Server aux Technical Learning Center (TLC). Le TLC est l’endroit où vous pourrez rencontrer les experts de toutes les technologies Microsoft, mais aussi de pouvoir “jouer” et dérouler les démos produits. Durant ces tech-ed, une session Commerce Server est au programme. Elle aura lieu le 10 novembre 2009 (pour plus d’information: Build Custom E-Commerce Solutions Faster and Easier with Microsoft Commerce Server 2009 (OFS06-IS) En espérant vous y croiser nombreux :) October 09 [Windows 2008] Configurez facilement votre serveur Windows 2008 CoreJe suis tombé sur un outil vraiment très très très pratique: Core Configuration for Windows 2008 - Smart-X Pour l’utiliser, il vous faut copier le msi sur votre serveur core et l’executer Un petit reboot et zou vous allez pouvoir en un clic (ou deux) configurer votre réseau, ajouter un AD etc., etc. N’en déplaise aux puristes de la ligne de commande, mais c’est diablement pratique ;) Seul petit bémol, cet outil n’est disponible qu’en mode non commercial, ie pas sur vos serveurs de production… Bon amusement |
|
|