Microsoft Dynamics Crm Sdk - 此查询是否可行?

时间:2014-03-08 17:29:19

标签: dynamics-crm-2011 dynamics-crm dynamics-crm-online dynamics-crm-2013

我正在探索用于通过Dynamics CRM SDK检索数据的“QueryExpression”机制,我认为我已经遇到了SDK的问题/限制,但我想确定这一点......

鉴于这个理想的SQL:

Select C.firstname, C.lastname 
FROM contact C 
INNER JOIN customeraddress A on C.contactid = A.parentid
WHERE 
((C.firstname = 'Max' AND C.lastname = 'Planck') OR (C.firstname = 'Albert' AND C.lastname = 'Einstein'))
OR 
A.Line1 = 'The secret moonbase'

我似乎无法将上述过滤条件(where子句)转换为等效的SDK条件/ filterexpressions等。

如您所见,我想查询: -

  1. 联系,加入到customeraddress(简单来说,只需在查询表达式中添加一个链接实体),
  2. 联系人是Albert Einstein或Max Planck(再次,这很简单,将FilterExpressions添加到QueryExpression)
  3. OR customeraddress'line1'等于'秘密月球基地'(这是有问题的位,只要我将过滤条件附加到LinkEntity,动态使用“AND”与标准相结合/过滤主要实体。
  4. 所以我在上面第3点描述的问题意味着我无法查询动态:

    1. (Albert Einstein或Max Planck)或任何住在秘密月球基地的人。
    2. 这是SDK的当前限制吗?

2 个答案:

答案 0 :(得分:5)

好的,我已经找到了答案,部分归功于@mwrichardsone,他促使我探索Dynamics Crm Linq查询提供程序如何做到这一点,然后我就可以从那里向后工作..

所以这里是等效的Linq查询表达式(我正在使用CrmOrganisationServiceContext): -

var contactsQuery = from c in orgService.CreateQuery("contact")
                    join a in orgService.CreateQuery("customeraddress") on (Guid)c["contactid"] equals (Guid)a["parentid"]
                                where (((string)c["firstname"] == "Max" && (string)c["lastname"] == "Planck")
                                || ((string)c["firstname"] == "Albert" && (string)c["lastname"] == "Einstein"))
                                || (string)a["line1"] == "The secret moonbase"
                    select c;

然后我发现这篇文章解释了如何将linq查询转换为Query Expression或Fetch Xml:http://pogo69.wordpress.com/2012/04/05/crm-linq-provider-converting-expressions-to-queryexpression-andor-fetchxml/

一旦我应用了这种技术,我就能看到等效的QueryExpression看起来像什么......基本上,我缺少的那一点(关键洞察力)是当你添加一个ConditionExpression时你可以设置它的“EntityName”。这意味着您可以将ConditionExpression添加到父/主实体上的过滤器组,即使该条件实际上是针对链接实体上存在的属性(在本例中为customeraddrress line1)。我假设你必须将条件添加到具有该特定属性的linkentity中 - 这也是@Henk van Boeijen在他的答案中所做的 - 并且没有给出正确的结果。

所以最终工作的QueryExpression看起来像这样(注意地址行1的条件没有添加到地址链接实体,它被添加到主实体上的过滤器组,并且它有一个“实体名称”设置为链接实体的别名)

var orgService = serviceProvider.GetOrganisationService();
        using (orgService as IDisposable)
        {

            var query = new QueryExpression("contact");
            query.ColumnSet.AddColumn("firstname");
            query.ColumnSet.AddColumn("lastname");

            // so link in customer address.
            query.AddLink("customeraddress", "contactid", "parentid", JoinOperator.Inner);
            var addressLink = query.LinkEntities[0];
            addressLink.EntityAlias = "A";
            addressLink.IncludeAllColumns();

            // conditions for max planck
            var firstName1Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Max");
            var lastname1Condition = new ConditionExpression("lastname", ConditionOperator.Equal, "Planck");

            // Groups those conditions using an "AND" conjunction.
            var maxPlankFilter = new FilterExpression(LogicalOperator.And);
            maxPlankFilter.AddCondition(firstName1Condition);
            maxPlankFilter.AddCondition(lastname1Condition);

            // conditions for albert einstein
            var firstname2Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Albert");
            var lastname2Condition = new ConditionExpression("lastname", ConditionOperator.Equal, "Einstein");

            // Groups those conditions using an "AND" conjunction.
            var albertEinsteinFilter = new FilterExpression(LogicalOperator.And);
            albertEinsteinFilter.AddCondition(firstname2Condition);
            albertEinsteinFilter.AddCondition(lastname2Condition);

            // could optionally chain the 2 filters so we get Albert's contitions chained (using AND) to max's conditions 
            //  albertEinsteinFilter.AddFilter(maxPlankFilter);

            // conditions for address line 1 moonbase
            var addressLine1Filter = new FilterExpression(LogicalOperator.And); 
            var line1Condition = new ConditionExpression("A", "line1", ConditionOperator.Equal, "The secret moonbase");
            addressLine1Filter.AddCondition(line1Condition);


            // add filters to query 
            // ensures each filter that we add to our queries criteria is chained together using an OR.
            query.Criteria.FilterOperator = LogicalOperator.Or;
            query.Criteria.AddFilter(albertEinsteinFilter);
            query.Criteria.AddFilter(maxPlankFilter);
            query.Criteria.AddFilter(addressLine1Filter);

            var results = orgService.RetrieveMultiple(query);
            int resultCount = 0;
            foreach (var r in results.Entities)
            {
                resultCount++;
                Console.WriteLine(string.Format("{0} {1} {2}", (string)r["firstname"], (string)r["lastname"], (string)((AliasedValue)r["A.line1"]).Value));
            }
            Console.WriteLine("There were " + resultCount + " results..");


        }

附注:如果您希望查看构建查询表达式的更短语法,请参阅下面的@Henk van Boeijen的帖子。如果生产力确实是您真正关心的问题,我将不得不回应下面@Nicknow的评论,并建议您认真考虑使用Linq查询机制来执行CRM查询。

@Henk van Boeijen也指出我的答案是基于仅出现在2013 SDK中的功能,并且似乎不在以前的版本中。我没有亲自检查过,但是如果你没有使用最新版本的SDK,那么这些信息对你来说可能非常有用。

答案 1 :(得分:1)

实际上非常简单;使用LogicalOperator和LinkEntity。

我建议添加DISTINCT谓词。

private IEnumerable<Entity> QueryExpression(IOrganizationService service)
{
    var query = new QueryExpression("contact");
    query.Distinct = true;
    query.ColumnSet.AddColumns("firstname", "lastname");

    query.Criteria.FilterOperator = LogicalOperator.Or;
    var f1 = query.Criteria.AddFilter(LogicalOperator.And);
    f1.AddCondition("firstname", ConditionOperator.Equal, "Max");
    f1.AddCondition("lastname", ConditionOperator.Equal, "Planck");

    var f2 = query.Criteria.AddFilter(LogicalOperator.And);
    f2.AddCondition("firstname", ConditionOperator.Equal, "Albert");
    f2.AddCondition("lastname", ConditionOperator.Equal, "Einstein");

    var link = query.AddLink("customeraddress", "contactid", "parentid");
    link.EntityAlias = "ca";
    query.Criteria.AddCondition("ca", "line1", ConditionOperator.Equal, "The secret moonbase");

    var response = service.RetrieveMultiple(query);

    return response.Entities;
}

请务必注意,此查询使用Dynamics CRM 2013中添加的新功能。它在Dynamics CRM 2011中不起作用,因为在该版本中,无法在{}中指定实体名称(或其别名) {1}}。