0
votes

I am experimenting with the example CalculatePrice on the Dynamics CRM example page. And im having a hard time understanding how to get products and bundles in a good manner.

What i wanna try and do is get products from an order with a productstructure attribute and a producttypecode. But it seems whatever i try i get a error The given key was not present in the dictionary.

The query below should look for productID from salesorder based on productID

            QueryExpression query = new QueryExpression("salesorderdetail");
            query.ColumnSet.AddColumns("quantity", "salesorderispricelocked", "priceperunit", "producttypecode", "_productid_value");
            query.Criteria.AddCondition("salesorderid", ConditionOperator.Equal, entity.Id);

            QueryExpression query2 = new QueryExpression("product");
            query2.ColumnSet.AddColumns("productstructure", "productnumber" , "productid");
            query.Criteria.AddCondition("productid", ConditionOperator.Equal, ec.Entities["_productid_value"]);

Then i try to iterate the list of objects to see if they have productstructure and their producttypecode

            for (int i = 0; i < ec.Entities.Count; i++)
            {
            if (ec.Entities[i].GetAttributeValue<int>("producttypecode") == 6)
            { you are a product 
            if (ec.Entities[i].GetAttributeValue<int>("productstructure") == 3){ you are a bundle

This is the link to the sample code i use: https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/sample-calculate-price-plugin

1

1 Answers

0
votes

For starters, the _productid_value notation is the WebAPI's way to access a lookup field. To access the productid using the SDK's late-bound paradigm, use:

myEntity["productid"] or

myEntity.GetAttributeValue<Guid>("productid") or

myEntity.GetAttributeValue<EntityReference>("productid").

Beyond that, since Product is a lookup on the OrderDetail, using a couple LinkEntity objects you could get away with a single query.

I would probably use LINQ and do something like this:

private void getProducts(Guid salesOrderId)
{
    using (var context = new Microsoft.Xrm.Sdk.Client.OrganizationServiceContext(svc))
    {
        var query = from od in context.CreateQuery("salesorderdetail")
                    join so in context.CreateQuery("salesorder") 
                    on od.GetAttributeValue<Guid>("salesorderid") equals so.GetAttributeValue<Guid>("salesorderid")
                    join p in context.CreateQuery("product")
                    on od.GetAttributeValue<Guid>("productid") equals p.GetAttributeValue<Guid>("productid")
                    where od.GetAttributeValue<Guid>("salesorderid").Equals(salesOrderId)
                    select new
                    {
                        OrderDetailId = od.GetAttributeValue<Guid>("salesorderdetailid"),
                        ProductId = od.GetAttributeValue<EntityReference>("productid"),
                        Quantity = od.GetAttributeValue<decimal?>("quantity"),
                        IsPriceLocked = so.GetAttributeValue<bool?>("ispricelocked"),
                        PricePerUnit = od.GetAttributeValue<Money>("priceperunit"),
                        ProductTypeCode = od.GetAttributeValue<OptionSetValue>("producttypecode"),
                        ProductStructure = p.GetAttributeValue<OptionSetValue>("productstructure"),
                        ProductNumber = p.GetAttributeValue<string>("productnumber")
                    };
        var results = query.ToList();
        var products = results.Where(e => e.ProductStructure.Value == 6).ToList();
        var bundles = results.Where(e => e.ProductStructure.Value == 3).ToList();                
    }
}

Please note that local variables results, products, and bundles are an anonymous type. You can loop through and access the properties of each object, but there's also a strong chance you'd want to cast them into instances of a real class.