jordimontana82 / fake-xrm-easy

The testing framework for Dynamics CRM and Dynamics 365 which runs on an In-Memory context and deals with mocks or fakes for you
https://dynamicsvalue.com/get-started/overview?source=git
Other
263 stars 182 forks source link

Query on associatedentitytypecode should work with both Entity Name and ObjectTypeCode #569

Open bwmodular opened 3 years ago

bwmodular commented 3 years ago

Describe the bug When you query the documenttemplate table in CRM, and you add a filter on the 'associatedentitytypecode' column, you can pass this either as an integer (the objecttypecode) or as a string (the table name). When you perform the same query against fakeXrmEasy, it fails if you pass in the object type code, as it tries to perform the string method 'ToLowerInvariant' on the integer.

This is the error: Method 'System.String ToLowerInvariant()' declared on type 'System.String' cannot be called with instance of type 'System.Int32'

To Reproduce Here's code that will work in Dynamics 365 online (sorry couldn't get github to format it better): void Main() { IOrganizationService service = MyExtensions.ConnectToCrm(MyExtensions.Environments.BLAH_DEV); GetTemplateWithEntityName(service).Dump("Query with entity Name"); GetTemplateWithEntityTypeCode(service).Dump("Query with ObjectTypeCode"); }

Guid GetTemplateWithEntityTypeCode(IOrganizationService service) { QueryExpression query = new QueryExpression("documenttemplate"); query.Criteria.AddCondition("name", ConditionOperator.Equal, "Order Summary"); //query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, "salesorder"); query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, 1088);

EntityCollection templates = service.RetrieveMultiple(query);       
return templates.Entities[0].Id;

}

Guid GetTemplateWithEntityName(IOrganizationService service) { QueryExpression query = new QueryExpression("documenttemplate"); query.Criteria.AddCondition("name", ConditionOperator.Equal, "Order Summary"); query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, "salesorder"); //query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, 1088);

EntityCollection templates = service.RetrieveMultiple(query);

return templates.Entities[0].Id;

} ...and here's similar code which fails in fakeXrmEasy:

void Main() { XrmFakedContext fakedContext = new XrmFakedContext(); IOrganizationService service = fakedContext.GetOrganizationService(); DocumentTemplate documentTemplate = new DocumentTemplate() { Id = Guid.NewGuid(), Name = "Order Summary", AssociatedEntityTypeCode = "salesorder", Status = false };
fakedContext.Initialize(new List { documentTemplate });

GetTemplateWithEntityName(service).Dump("Query with entity Name");
GetTemplateWithEntityTypeCode(service).Dump("Query with ObjectTypeCode");   

}

Guid GetTemplateWithEntityTypeCode(IOrganizationService service) { QueryExpression query = new QueryExpression("documenttemplate"); query.Criteria.AddCondition("name", ConditionOperator.Equal, "Order Summary"); //query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, "salesorder"); query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, 1088);

EntityCollection templates = service.RetrieveMultiple(query);
return templates.Entities[0].Id;

}

Guid GetTemplateWithEntityName(IOrganizationService service) { QueryExpression query = new QueryExpression("documenttemplate"); query.Criteria.AddCondition("name", ConditionOperator.Equal, "Order Summary"); query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, "salesorder"); //query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, 1088);

EntityCollection templates = service.RetrieveMultiple(query);

return templates.Entities[0].Id;

}

FakeXrmEasy and Dynamics 365 / CRM version Version 9 of FakeXrmEasy, v 1.57.1, Dynamics 365 online Screenshots If applicable, add screenshots to help explain your problem. Working in 'real' instance image Not working in tests image

Not a showstopper, but a definite difference between D365 online and FakeXrmEasy...

jordimontana82 commented 3 years ago

Thanks for raising this Ben.

What is the type of associatedentitytypecode property that is generated? I'm wondering if using fake metadata to declare it as an integer will solve it for the time being...

bwmodular commented 3 years ago

Hi Jordi It's a string: image How would I fake the metadata as a workaround for now?

jordimontana82 commented 3 years ago

I'm guessing this will have to be resolved in the condition expression evaluation. We could try and convert values to their string representation if the associated type was a string and the value wasn't a string already. It would allow then to use the object type code like:

DocumentTemplate documentTemplate = new DocumentTemplate() { Id = Guid.NewGuid(), Name = "Order Summary", AssociatedEntityTypeCode = "1088", Status = false };

Right now, in order to make it work, the QueryExpression will have to use the object type code as a string value, i.e.

query.Criteria.AddCondition("associatedentitytypecode", ConditionOperator.Equal, "1088");

Could you try passing in the object type code as a string to see if that works against the real D365 online? If so, that might be the workaround for the time being...

bwmodular commented 3 years ago

Unfortunately, if I try and pass the entity type code as a string, I get this error: The entity with a name = '1088' with namemapping = 'Logical' was not found in the MetadataCache.

jordimontana82 commented 3 years ago

Thanks Ben, so fix in query translation so....