Boite à outils Office

Linq pour CommerceServer : merci CSMetal !

Commerce Server, Développement No Comments »

Il y a déjà quelques semaines, Kerry Havas, Architecte Produit Commerce Server, a publié la version 2 de CSMetal.

Qu’est-ce que CSMetal ? C’est un utilitaire pour Commerce Server qui génère des classes fortement typées utilisable à travers un provider LINQ basé sur l’API Commerce Foundation => ie, ça ne remplace pas l’API Commerce Foundation !

Kerry frappe fort avec CSMetal, car le développement sous Commerce Server devient un “jeu d’enfant”!

Avant de pouvoir utiliser le provider LINQ pour Commerce Server, il nous faut auparavant générer les entités. Pour cela, nous devons utiliser l’outil de commande en ligne CSMetal.

Pour que CSMetal entre en action, il vous faut:

  • Le fichier ChannelConfiguration.config correctement configuré
    • Attention de bien mettre la valeur de l’attribut useSharedCommerceContexts à false.
    • Ajouter dans le noeud MessageHandler avec l’attribut name "CommerceQueryOperation_CommerceEntityDefinition" les noeuds enfant suivants:
   1: <!-- Note that RepositoryMetadataLoader is replaced by a slightly customized one -->

   2: <Component name="RepositoryMetadataLoader" type="Microsoft.Commerce.Metal.Generator.OperationSequenceComponents.RepositoryMetadataLoader, Microsoft.Commerce.Metal.Generator, Version=1.0.0.0, Culture=neutral" />

   3: <!-- Note that this is added to add overlay capability to the Metadata repository -->

   4: <Component name="MetadataOverlayProcessor" type="Microsoft.Commerce.Metal.Generator.OperationSequenceComponents.MetadataOverlayProcessor, Microsoft.Commerce.Metal.Generator, Version=1.0.0.0, Culture=neutral" />

      • Notez que le dernier noeud permet en gros de pouvoir générer d’autres entités ou attributs sans toucher au fichier MetadataDefinitions.xml. Nous y revenons plus bas.
  • Le fichier MetadataDefinitions.xml proprement mis à jour
    • Ajouter au noeud RelationshipTypes, un noeud enfant :
      • <RelationshipType name="Inherits"/>
    • Consultez le fichier “CSMetal_Beta2_ReadMe.rtf” pour ajouter à 2 entités:
      • Basket
        • les énumérations des status de commande
      • Ads
        • Les énumérations des tailles d’une publicité
  • Les “traditionnels” OrderObjectMappings.xml et OrderPipelineMappings.xml, eux aussi mis à jour.

Une fois ces ingrédients sous la main, mettez-les par exemple dans un répertoire temporaire. Ajoutez les fichiers nécessaires à la bonne exécution de CSMetal:

  • CSMetal.exe Smile
  • CSMetal.exe.config qui est une copie du web.config de votre application web
  • GeneratorSettings.xml qui vous permet de définir les dossiers d’outputs pour les assemblies générées avec un namespace et un nom de context de votre choix!
  • Microsoft.Commerce.Metal.Generator.dll pour la génération de code

Soit:

image

Afin de bénéficier pleinement du Linq provider pour Commerce Server, nous avons certaines metadatas à faire évoluer ou créer. Pour cela, Kerry a introduit un concept très pratique appellé “MetaDataOverlays”:

  • Cela revient à étendre les metadatas via un fichier xml extérieur sans avoir à toucher à votre fichier MetadataDefinitions.xml. Dans le cas de notre provider Linq pour Commerce Server, nous avons un certains nombres d’entités à mettre à jour mais qui n’ont pas d’intéret à être dans le runtime de l’application web puisqu’utilisé uniquement par notre provider Linq.

Pour cela, dans le répertoire CSMetal ajouter un nouveau dossier enfant appellé MetadataOverlays et ajoutez-y le fichier xml Metadata_CSMetal.xml

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <!-- 

   3: This file contains the Metadata Repository

   4: -->

   5: <MetadataDefinitions xmlns="urn:schemas-microsoft-multi-channel-commerce-foundation-metadata">

   6:     <DefaultChannel>

   7:         <CommerceEntities>

   8:             <!-- Added for Linq based Search -->

   9:             <CommerceEntity name="CatalogEntity">

  10:                 <DisplayName value="Catalog Entity" />

  11:                 <Properties>

  12:                     <Property name="Phrase"    dataType="String">

  13:                         <DisplayName value="Phrase"/>

  14:                     </Property>

  15:                     <Property name="ReturnTypes"    dataType="Integer">

  16:                         <DisplayName value="Return Types"/>

  17:                     </Property>

  18:                     <Property name="FirstItem"    dataType="Integer">

  19:                         <DisplayName value="First Item"/>

  20:                     </Property>

  21:                     <Property name="WhereClause"    dataType="String">

  22:                         <DisplayName value="Where Clause"/>

  23:                     </Property>

  24:                     <Property name="TotalItemCount"    dataType="Integer">

  25:                         <DisplayName value="Total Item Count"/>

  26:                     </Property>

  27:                     <Property name="ResultsPerPage"    dataType="Integer">

  28:                         <DisplayName value="Results Per Page"/>

  29:                     </Property>

  30:                 </Properties>

  31:             </CommerceEntity>

  32:             <!-- Added for Linq based Search -->

  33:  

  34:             <!-- Catalog Start -->

  35:             <CommerceEntity name="Catalog">

  36:                 <Relationships>

  37:                     <Relationship name="DependantCatalogs" type="Relationship" modelName="Catalog" isMultipleItems="true" >

  38:                         <DisplayName value="Dependant Catalogs" />

  39:                     </Relationship>

  40:                     <Relationship name="SourceCatalogs" type="Relationship" modelName="Catalog" isMultipleItems="true" >

  41:                         <DisplayName value="Source Catalogs" />

  42:                     </Relationship>

  43:                 </Relationships>

  44:             </CommerceEntity>

  45:  

  46:             <!-- CreditCard Start -->

  47:             <CommerceEntity name="CreditCard">

  48:                 <Relationships>

  49:                     <Relationship name="PaymentAccount" type="Inherits" modelName="PaymentAccount" isMultipleItems="false">

  50:                     </Relationship>

  51:                 </Relationships>

  52:             </CommerceEntity>

  53:  

  54:             <!-- Basket Start -->

  55:             <CommerceEntity name="Basket">

  56:                 <Relationships>

  57:                     <Relationship name="LineItems" modelName="LineItem" type="Relationship" isMultipleItems="true" />

  58:                     <Relationship name="Addresses" modelName="Address" type="Relationship" isMultipleItems="true" />

  59:                     <Relationship name="Payments" modelName="Payment" type="Relationship" isMultipleItems="true" />

  60:                     <Relationship name="Shipments" modelName="Shipment" type="Relationship" isMultipleItems="true" />

  61:                     <Relationship name="RequestedPromoCodes" modelName="RequestedPromoCode" type="Relationship" isMultipleItems="true" />

  62:                 </Relationships>

  63:             </CommerceEntity>

  64:  

  65:             <!-- ShopperList Start -->

  66:             <CommerceEntity name="ShopperList">

  67:                 <Relationships>

  68:                     <Relationship name="LineItems" modelName="LineItem" type="Relationship" isMultipleItems="true" />

  69:                 </Relationships>

  70:             </CommerceEntity>

  71:  

  72:             <!-- LineItem Start -->

  73:             <CommerceEntity name="LineItem">

  74:                 <Relationships>

  75:                     <Relationship name="ItemLevelDiscounts" modelName="Discount" type="Relationship" isMultipleItems="true" />

  76:                 </Relationships>

  77:             </CommerceEntity>

  78:  

  79:             <!-- CashCard Start -->

  80:             <CommerceEntity name="CashCard">

  81:                 <Relationships>

  82:                     <Relationship name="PaymentAccount" type="Inherits" modelName="PaymentAccount" isMultipleItems="false">

  83:                     </Relationship>

  84:                 </Relationships>

  85:             </CommerceEntity>

  86:  

  87:             <!-- GiftCertificate Start -->

  88:             <CommerceEntity name="GiftCertificate">

  89:                 <Relationships>

  90:                     <Relationship name="PaymentAccount" type="Inherits" modelName="PaymentAccount" isMultipleItems="false">

  91:                     </Relationship>

  92:                 </Relationships>

  93:             </CommerceEntity>

  94:  

  95:             <!-- Shipment Start -->

  96:             <CommerceEntity name="Shipment">

  97:                 <Relationships>

  98:                     <Relationship name="ShippingMethod" modelName="ShippingMethod" type="Relationship" isMultipleItems="false" />

  99:                 </Relationships>

 100:             </CommerceEntity>

 101:  

 102:             <!-- Payment Start -->

 103:  

 104:             <!-- PaymentAccount Start -->

 105:             <CommerceEntity name="PaymentAccount">

 106:                 <Properties>

 107:                     <Property name="Id" dataType="String">

 108:                         <DisplayName value="Id"/>

 109:                         <Description value="Unique ID of the payment." />

 110:                     </Property>

 111:                     <Property name="CustomerName" dataType="String">

 112:                         <DisplayName value="CustomerName"/>

 113:                         <Description value="Name of Customer." />

 114:                     </Property>

 115:                     <Property name="BillingAddressId" dataType="String">

 116:                         <DisplayName value="BillingAddressId"/>

 117:                         <Description value="Id of billing address" />

 118:                     </Property>

 119:                     <Property name="DisplayName" dataType="String">

 120:                         <DisplayName value="DisplayName"/>

 121:                         <Description value="DisplayName." />

 122:                     </Property>

 123:                 </Properties>

 124:                 <Relationships>

 125:                     <Relationship name="PaymentMethod" modelName="PaymentMethod" type="Relationship" isMultipleItems="false" />

 126:                 </Relationships>

 127:             </CommerceEntity>

 128:             

 129:             <CommerceEntity name="Payment">

 130:                 <Relationships>

 131:                     <Relationship name="PaymentAccount" modelName="PaymentAccount" type="Relationship" isMultipleItems="false" />

 132:                 </Relationships>

 133:             </CommerceEntity>

 134:         </CommerceEntities>

 135:     </DefaultChannel>

 136: </MetadataDefinitions>

Exécutez maintenant CSMetal.exe:

image

Dans le répertoire configuré dans le GeneratorSettings.xml, vous trouverez 3 fichiers .cs correspondant à vos entités Commerce Server :

image

Vous noterez un fichier odata généré qui sera particulièrement utile pour exposer nos données Commerce Server, mais cela fera l’objet de plusieurs autres posts Smile

Copiez les fichiers GeneratedContexts.cs et GeneratedTypes.cs générés par CSMetal dans le repertoire GeneratedTypes du projet CSMetalLinqProvider (ou mettez les dans les paramètres output de CSMetal, ie le fichier GeneratorSettings.xml, pour ne pas avoir à les copier) et relancez une compilation du projet CSMetalLinqProvider.

Vos entités sont maintenant générées et le provider Linq disponible Smile

 

Récuperer une catégorie reviens maintenant à:

var category = new CategoryContext(commerceServiceProxy)
                  .IncludeChildCategories()
                  .Single(o => o.Id=="Departments" && o.CatalogId==DefaultCatalog);
var childCategories = category.ChildCategories;
ou pour un produit :
var product = new ProductContext(commerceServiceProxy)
                 .Single(o=>o.CatalogId==DefaultCatalog && o.Id=="AW200-12")
var productCode = product.ProductCode;

Ce n’est qu’un petit échantillon de ce que l’on peut faire, et d’autres posts viendront bientôt vous montrer la puissance de ce provider Smile => Pour vos développeurs, plus besoin de connaitre en profondeur CS pour pouvoir l’attaquer et donc faciliter l’adoption de Commerce Server.

Comment prévisualiser vos données marketing avec Commerce Server

Commerce Server, Développement 1 Comment »

Comme vous devez le savoir, Microsoft Commerce Server via le Marketing System vous permets de gérer les compagnes marketing de votre site e-Commerce via les modules:

Ces modules sont tous horodatables. C’est à dire que vous allez pouvoir définir la date de début et date de fin d’affichage/application d’une opération commerciale ou d’une publicité.

Par défaut, le client riche Marketing, vous permets de visualiser une publicité pour vous donner une idée de son rendue:

image

Et là, comme la majorité de mes clients, vous allez me dire : “ok, je peux voir ma publicité, mais qu’est-ce que cela va donner sur mon site ? Comment m’assurer que le contenu et contenant soit correcte ? Et quid des opérations commerciales ?”

Si la publicité ou l’opération commerciale en question est prévue de s’afficher maintenant, il suffit d’ouvrir votre site pour voir les contenus publicitaires s’afficher et les opérations commerciales s’appliquer… ou non ! N’oubliez pas que vos contenus peuvent être soumis à condition, comme:

  • la publicité ne s’affiche que sur une certaine catégorie de pages (home, produits, panier, …),
  • la publicité ne s’affiche ou l’opération commerciale ne s’applique que si une caractéristique de l’utilisateur connecté remplis une condition (utilisateur est un homme ou une femme, …)
  • etc, etc, … (si vous avez des questions n’hésitez pas à m’en parler Sourire)

image

Mais que faire lorsque vos opérations commerciales sont prévues pour dans 2 ou 3 mois ? Devez-vous attendre le jour J tout tremblant pour voir le résultat ? La réponse est non! Sourire (ouf… l’honneur est sauf).

Dans les solutions possibles, et fonction de la qualité de votre consultant Commerce Server, vous aurez comme réponse:

  • “Ce n’est pas possible, Commerce Server ne sait pas gérer cela!”
  • “Changez la date de votre serveur et rafraîchissez votre cache pour voir le résultat” (véridique!)
    • Pratique si votre environnement de staging et sur la même machine que celui de production Envieux 
    • Oblige une intervention sur la plateforme d’hébergement par l’équipe IT
      • Pas idéal, si chaque prévisualisation demande le bien vouloir de l’IT qui en général à bien d’autres choses à faire (du moins j’espère Ange)
      • Ne pas oubliez de revenir à la vrai date du jour
  • “Désactivez les opérations commerciales en cours puis n’activez que celles que vous souhaitez voir tout en changeant leurs dates d’application pour qu’elles s’appliquent sur le champ.”
    • Fastidieux, j’ai des clients qui ont quasi cent publicités à afficher et bien souvent autant d’opérations commerciales (voir plus)…
    • Risque de confusion sur les activations ou désactivations
      • Toutes celles désactivées sont-elles à réactiver? Ou comment oublier facilement celles activées…
    • Risque d’erreur en changeant les dates pour les remettre sur la période souhaitée
    • Certains diront qu’un petit développement custom pourrait très bien activé/désactivé une liste de publicité/opération commerciale et changer les dates d’application. Cela est vrai mais ça reste quand même un peu bancal…
  • “Pas de soucis, nous avons la solution!”… et maintenant grâce à cet article nos précédents “experts” ont la solution grâce à la suite de ce post Clignement d'œil

La solution est en fait très simple. Lors du premier chargement de l’application web, le runtime de Commerce Server va charger de nombreuses informations dans son cache et context afin d’améliorer les performances d’exécution du site.

Ce remplissage du cache se fait via 2 procédures stockées (et une autre indirectement) situées dans la base de données marketing:

  • mktg_spRuntimeLoadAdvertisements
  • mktg_spRuntimeLoadDiscounts
  • mktg_spRuntimeLoadReferenceTables

 

imageimageimage

=> Ces procédures stockées sont exécutées par le runtime à chaque démarrage du site ou rafraichissement du cache.

 

L’équipe produit de Commerce Server ayant très bien fait les choses, il est possible de dire au runtime de Commerce Server de charger d’autres procédures stockées que celles-ci et donc d’y inclure notre propre logique.

L’idée ici, est d’avoir une application web de prévisualisation où nous viendrons faire charger par le runtime nos propres procédures stockées et une autre application web de production ou staging avec le comportement “par défaut”.

Afin d’exécuter d’autres procédures stockées à charger par le runtime de Commerce Server, il nous faut modifier la gestion du cache via une section du fichier web.config > CommerceServer > Caches (voir MSDN: caches Element).

Dans le web.config  de notre application web de prévisualisation, nous allons donc spécifier ces configurations de caches avec ces valeurs:

<cache
    name="Advertising"
    type="Advertising"
    refreshInterval="900"
    retryInterval="30"
    loaderProgId="Commerce.CSFLoadAdvertisements"
    writerProgId="Commerce.CSFWriteEvents">
    <config
        key="LoadAdvertisementsProcedure"
        value="spGael_staging_mktg_spRuntimeLoadAdvertisements" />
</cache>
<cache
    name="Discounts"
    type="Discounts"
    refreshInterval="0"
    retryInterval="30"
    loaderProgId="Commerce.CSFLoadDiscounts"
    writerProgId="Commerce.CSFWriteEvents">
    <config
        key="LoadDiscountsProcedure"
        value="spGael_staging_mktg_spRuntimeLoadDiscounts" />
</cache>

Comme les différents composants de pipeline prennent tous comme axe de calcul la date et l’heure du moment de l’appel, vouloir changer cela reviendrait à en redévelopper l’intégralité… Fastidieux et risqué, surtout que pour beaucoup, les pipelines sont une espèce de boite noire qu’il ne faut pas toucher…

Afin de contourner cela, l’idée est de faire venir le futur à nous Sourire en calculant le nombre de jours qui nous sépare de la date de prévisualisation et de le retrancher à l’ensemble de nos dates de début et date de fin!

Reprenons la procédure stockée “mktg_spRuntimeLoadAdvertisements” qui charge les publicités actives dans le time frame du jour:

image

On se rend compte que l’on récupère l’ensemble des publicités  applicable à la date du 8 juillet 2010. Pour ma démonstration, j’ai créé une bannière publicitaire qui s’appliquera du 01/08/2010 au 31/08/2010:

image

En exécutant de nouveau ma procédure stockée mktg_spRuntimeLoadAdvertisements, j’obtiens les même résultats que précédemment. Etonnant? Non, puisque ma nouvelle publicité n’est pas éligible !Sa  date de début est au 1er août et nous sommes le 8 juillet 2010:

image[21]

Comme expliqué précédemment, nous allons reprendre la procédure stockée précedente (“mktg_spRuntimeLoadAdvertisements”) pour en créer une nouvelle, que nous appellerons “spGael_staging_mktg_spRuntimeLoadAdvertisements”. Dans cette procédure, nous allons changer les dates de début et date de fin en retranchant le nombre de jour qui sépare la date de prévisualisation à celle d’aujourd’hui.

imageVous noterez au passage que la date de prévisualisation est stockée dans une table appelée altima_doPreview qui ne contient qu’une seule colonne et une seule ligne.

Sur l’exécution de ma procédure stockée, j’obtiens ici qu’un seul résultat, puisque seule ma publicité est valide à la date du 15 août 2010:

image

Dans ce résultat, nous constatons bien que la date de début de ma publicité a basculé au 25 juin 2010 et la date de fin au 25 juillet 2010. En effet, 37 jours séparent le 08 juillet 2010 (date du jour) au 15 août 2010 (date de la prévisualisation). Soit sur ma publicité :

  • Date de début: 1er août 2010 – 37 jours => 25 juin 2010
  • Date de fin:, 31 août 2010 – 37 jours => 25 juillet 2010

Lançons maintenant notre application web de preview (n’oubliez pas de mettre à jour le web.config comme spécifié précédemment), et miracle… Sourire

image

Mon application “normale” affiche bien quant à elle, les publicités actives et applicables du moment

image

Pour terminer, je vous livre ci-dessous la procédure stockée qui vous chargera vos opérations commerciales en mode preview:

image

A vous maintenant la prévisualisation !

Comment consommer ses données Commerce Server pour Power Pivot via un service de données REST

.Net, Commerce Server, Développement, WCF 1 Comment »

Suite à mes deux posts sur Commerce Server et Power Pivot (Créer des rapports simples et efficaces pour Commerce Server grâce à PowerPivot (aka Gemini) et Comprendre et analyser vos données Commerce Server grâce à Power Pivot), j’ai reçu quelques questions concernant la récupération des données provenant de Commerce Server.

En effet, il n’est pas rare (j’ose difficilement concevoir la chose autrement) que le(s) serveur(s) e-Commerce soi(en)t hébergé(s) sur un data center déconnecté de l’environnement de l’entreprise (du webmaster, du consultant,…), rendant donc impossible une connexion directe à la base de données.

Que faire donc pour récupérer les données et les exploiter?

  • Réplication SQL Server entre l’environnement de production et votre environnement local
    • Avantages:
      • Nombreuses possibilités de synchronisations (temps réels ou différés)
      • Technologie éprouvée et robuste
    • Inconvénients:
      • Nécessite d’avoir un SGBD (oui tous les consultants n’ont pas un SGBD Smile)
      • Exposer sa base de données, qui normalement doit être derrière la DMZ (même si vous filtrez les IPs ce n’est quand même pas génial en terme de sécurité ou passer par une LS)
  • Exporter les données dans un format texte pour le réintégrer dans l’environnement de base de données local
    • Avantages:
      • Possibilité d’importer de nombreux types de fichiers textes formatés dans Excel
      • Ouverture/Import des fichiers textes comme sous Excel
    • Inconvénients:
      • L’import de fichiers dans Excel n’est pas toujours simple à appréhender par un novice
      • Gestion de plusieurs fichiers pouvant être complexes à maintenir et gérer
  • Utilisez la capacité de PowerPivot à consommer un flux de données type RSS (voir la MSDN à ce sujet)
    • Avantages:
    • Inconvénients:
      • Technologie encore récente
      • Nécessite d’utiliser un protocol https ou une LS pour garantir une bonne sécurisation du transfert de données.

Ces 3 solutions ont chacune leurs avantages et inconvénients et le choix dépend fortement de votre architecture et vos besoins (ie pas de règles figées dans le marbre!). Pour ma part, j’ai décidé de vous présenter la dernière solution: à savoir un flux de données de type RSS.

Pour exposer vos données en asp.net, l’idéal est d’utiliser un service WCF qui se chargera de rendre vos données au format désiré (ici l’ATOM). Bien que l’exposition de vos données au travers d’un service WCF n’est pas nouvelle (il en existe de nombreuses façons pour le réaliser), l’exposer nativement en mode REST et au format ATOM (ou json) pour la représentation des données via une URI (autrement dit, l’utilisation du protocol OData) l’est beaucoup moins!

Pour réaliser cela, nous avons besoin d’avoir une application web dans lequel nous allons ajouter une item de type “ADO.Net Entity Data Model” connecté à votre base de données SQL Server.

image

Dans le cas où vos rapports se basent sur les commandes, vous devez choisir la base de données <site commerce server>_Transactions.

 image

Ajoutez ensuite une item de type WCF Data Service

image

Dans le service créé, ajoutez à la méthode InitializeService le code suivant:

config.SetEntitySetAccessRule("DiscountsApplied", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("LineItems", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("OrderAddresses", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("OrderForms", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("PurchaseOrderPayments", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("PurchaseOrders", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("Shipments", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("ShippingDiscounts", EntitySetRights.AllRead);

 

Ceci vous permettant de donner un accès en lecture seule à vos entitées et donc par extension aux tables de la base de données.

Affichez votre service dans votre navigateur et vous obtenez automatiquement un flux XML Atom listant les différentes entités auxquelles vous avez accès.

image

Ajoutez par exemple LineItems à la fin de votre url (ex: http://localhost//CommerceServerOrdersDataService.svc/LineItems)

Votre navigateur affiche alors, une page similaire à n’importe quel flux RSS:

image

Pour afficher le flux XML à la place de l’interface RSS, allez dans les options internet > Contenus > Paramètres des flux RSS et décochez la case d’affichage RSS

image

image 

Et voilà la partie développement est terminée ! Vous pouvez consommer votre flux dans Power Pivot dès à présent:

image image image

image

Je vous montrerez dans un prochain post comment inclure les flux dans la même stratégie de sécurité que les web services Commerce Server.

Retrouvez plus d’informations sur:

ProductConfiguration / CategoryConfiguration ou les oubliés du développement Commerce Server !

Commerce Server, Développement No Comments »

Ces 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):

image image

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:

  • Sans ProductConfiguration:
Product product = catalogCtx.GetProduct("Adventure Works Catalog", "AW029-03");
Console.WriteLine("Pid: " + product.ProductId +
                  " - " + product.DisplayName +
                  " - " + product.ListPrice);

Grâce au SQL Profiler, nous pouvons récupérer les appels SQL Server et se rendre compte qu’ici 2 procédures stockées sont appelées:

image


  • Via un ProductConfiguration:
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);
Console.WriteLine("Pid: " + product.ProductId +
                  " - " + product.DisplayName +
                  " - " + product.ListPrice);

Cette fois-ci nous pouvons constater qu’une seule procédure stockée est appelée (car nous ne remontons pas les variants):

image

Read the rest of this entry »

Trier des propriétés Commerce Server selon des ordres de tri différents

Commerce Server, Développement No Comments »

Pour 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.

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in
Creative Commons License