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://learn.microsoft.com/en-us/dynamics365/customer-engagement/developer/sample-calculate-price-plugin
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.