1

I need to query from a CRM entity some values where a linked entity contains a string inside its name.

I try to explain:

  • I have new_supplycontract table.
  • This table, has an EntityReference named new_pod
  • The new_pod entity, has two fields: new_citypod and new_street
  • new_citypod points to another entity named new_city
  • new_street points to another entity named new_street

I need to query the new_supplycontract table to retrieve only the records whose new_pod contains a street which name contains a string I pass and a city which name contains another string i pass.

I know this code works for retrieving all new_supplycontract entities whose two text fields "new_city" and "new_address" are like to two strings passed.

QueryExpression query = new QueryExpression(new_supplycontract.EntityLogicalName);
query.ColumnSet = new ColumnSet(true);
query.Criteria.AddCondition("new_city", ConditionOperator.NotNull);
query.Criteria.AddCondition("new_address", ConditionOperator.NotNull);

query.LinkEntities.Add(new LinkEntity(new_supplycontract.EntityLogicalName, "new_comune", "new_city", "new_comuneid", JoinOperator.Inner)); 
query.LinkEntities[0].Columns.AddColumns("new_name");
query.LinkEntities[0].EntityAlias = "comuneTemp";
query.LinkEntities[0].LinkCriteria.AddCondition("new_name", ConditionOperator.Like, "%" + comune + "%");

query.LinkEntities.Add(new LinkEntity(new_supplycontract.EntityLogicalName, new_via.EntityLogicalName, "new_address", "new_viaid", JoinOperator.Inner));
query.LinkEntities[1].Columns.AddColumns("new_name");
query.LinkEntities[1].EntityAlias = "viaTemp";
query.LinkEntities[1].LinkCriteria.AddCondition("new_name", ConditionOperator.Like, "%" + via + "%");


DataCollection<Entity> entities = service.RetrieveMultiple(query).Entities;          

But I don't really know how to use this code for my goal. I don't know how to filter an entityreference's entityreference.

Any help will be appreciated

Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66
  • put this: new LinkEntity(new_supplycontract.EntityLogicalName, "new_comune", "new_city", "new_comuneid", JoinOperator.Inner); in a new variable. Then, you can add a link entity to that variable the same way you are doing here with query. That's how you chain them. – Lidaranis Dec 15 '16 at 14:50

3 Answers3

1

LinkedEntities can have nested LinkedEntities in CRM 2011. This was changed since 2013 where an EntityName attribute was introduced and there wasn't a need for having nested entities.

But basically, you could start from the supplycontract entity, then add a linked entity against your new_pod entity. From that Linked Entity, you'll need to add 2 linked entities, one to the new_city entity and another one to the new_street entity. Each of these 2 linked entities will need a contains condition expression where you pass the 2 strings you want to use for filtering.

Ex:

QueryExpression query = new QueryExpression(new_supplycontract.EntityLogicalName);
query.ColumnSet = new ColumnSet(true);
var le = query.LinkEntities.Add(new LinkEntity(new_pod.EntityLogicalName, "new_pod", "new_pod", "new_podid", JoinOperator.Inner)); 

var lePod = le.LinkEntities.Add(new LinkEntity(new_pod.EntityLogicalName, "new_city", "new_citypod", "new_cityid", JoinOperator.Inner));
var leCity = le.LinkEntities.Add(new LinkEntity(new_pod.EntityLogicalName, "new_street", "new_street", "new_streetid", JoinOperator.Inner));

//Add conditions to each nested linked entity now as above.

Now, I personally prefer LINQ cause the query is much more easier to read than using LinkedEntities.

Hope this helps.

Jordi
  • 1,460
  • 9
  • 9
  • Thanks for the answer! just a question: you used `var le = ..` but the `linkEntities.Add` is` void`. After you used `le.Linkentities.add ...` but I have to use everywhere `query.linkedentities.add...,` instead, right? – Pier Giorgio Misley Nov 29 '16 at 13:05
  • btw, just to know, I knew with linQ the "like" operator was not working on CRM, I tried it some weeks ago but without any success, is there a way to make it working? – Pier Giorgio Misley Nov 29 '16 at 13:06
  • Did you try .Contains("string")? Or alternatively .StartsWith("string") or .EndsWith("string"). .Contains might break the index and be really bad from a performance point of view unless using FULL TEXT indexes – Jordi Nov 29 '16 at 17:30
  • Yeah i tried them all, but they doesn't work.. starts and endswith are not good for my program, the perfect one would be "contains" but it doesn't works unfortunatly – Pier Giorgio Misley Nov 30 '16 at 08:24
1

I've ran into countless issues with LINQ to CRM, mostly due to my misunderstanding of how it works. Unfortunately, Query Expressions are extremely verbose and hard to read. I created and use the DLaB.Xrm library to make my life simpler (and more typed, I love me some EarlyBound Dev)

Here is your query using DLaB.Xrm:

var qe = QueryExpressionFactory.Create<new_supplycontract>();
var podLink = qe.AddLink<new_pod>(new_supplycontract.Fields.new_Pod, new_pod.Fields.Id);

podLink.AddLink<new_city>(new_pod.Fields.new_citypod,              // This is the attribute of the "from" entity to join on
                          new_city.Fields.Id,                      // This is the attribute of the "to" entity to join on.  If name is identical, this parameter can be removed
                          new ColumnSet(new_city.Fields.new_name)) // AliasedValue to add to the result
    .LinkCriteria.AddCondition("new_name", ConditionOperator.Like, "%" + comune + "%");

podLink.AddLink<new_street>(new_pod.Fields.new_street, 
                            new_street.Fields.Id,
                            ColumnSet(new_street.Fields.new_name))
    .LinkCriteria.AddCondition("new_name", ConditionOperator.Like,  "%" + via + "%");

var leads = service.GetEntities(qe);
Daryl
  • 18,592
  • 9
  • 78
  • 145
  • That is fantastic! just a question, trying to install the nuget package gives me an error: Could not install package 'DLaB.Common 1.0.1.13'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.5', but the package does not contain any assembly references or content files that are compatible with that framework. I could install the 1.0.0 version, but all other versions give me this error, I missed something? – Pier Giorgio Misley Nov 30 '16 at 08:33
  • @PierGiorgioMisley I think you have to target 4.5.2. – Daryl Nov 30 '16 at 14:01
  • Why not? it's an in place upgrade? https://blogs.msdn.microsoft.com/dotnet/2014/08/07/moving-to-the-net-framework-4-5-2/ – Daryl Dec 01 '16 at 15:03
0

You need to chain the link entities. Here's an example:

        ConditionExpression condition3 = new ConditionExpression();
        ...
        LinkEntity link3 = new LinkEntity();
        ...
        link3.LinkCriteria.Conditions.Add(condition3);

        ConditionExpression condition2 = new ConditionExpression();
        ...
        LinkEntity link2 = new LinkEntity();
        ...
        link2.LinkCriteria.Conditions.Add(condition2);

        LinkEntity link1 = new LinkEntity();
        ...
        link1.LinkEntities.Add(link2);
        link1.LinkEntities.Add(link3);

        QueryExpression query = new QueryExpression("");
        ...
        query.LinkEntities.Add(link1);

        DataCollection<Entity> entities = service.RetrieveMultiple(query).Entities;

It helps to write them separately and use .Criteria.Conditions.Add() instead of .Criteria.AddCondition()

Lidaranis
  • 765
  • 3
  • 9