我正在一个项目中进行工作,该项目需要使用Microsoft Dynamics CRM从xlsx文件执行匹配的用户输入数据。

我有一个执行匹配的方法。

public EntityViewModel Match(EntityViewModel inputEntity)
{

    try
    {

        // Connect to the Organization service.
        // The using statement assures that the service proxy will be properly disposed.
        using (var serviceProxy = CrmServiceFactory.CreateNew())
        {
            if (!string.IsNullOrEmpty(inputEntity.ClientName))
                CrmHelper.ClientMatch(serviceProxy, inputEntity);

            var product = false;

            if ((string.IsNullOrEmpty(inputEntity.Category) || inputEntity.Category != revenuecategoryos.Insurance.ToString())
                && !string.IsNullOrEmpty(inputEntity.ProductName) && !string.IsNullOrEmpty(inputEntity.ProductNumber) && inputEntity.ClientId != Guid.Empty)
            {

                product = CrmHelper.ClientAssetMatch(serviceProxy, inputEntity);
            }


            if (((string.IsNullOrEmpty(inputEntity.Category) && !product) || inputEntity.Category == revenuecategoryos.Insurance.ToString()) && !string.IsNullOrEmpty(inputEntity.ProductNumber) && !string.IsNullOrEmpty(inputEntity.ProductName))
            {

                CrmHelper.InsuranceMatch(serviceProxy, inputEntity);
            }

            if (!string.IsNullOrEmpty(inputEntity.ProductProvider) && !string.IsNullOrEmpty(inputEntity.ProductNumber) && !string.IsNullOrEmpty(inputEntity.ProductName))
            {

                CrmHelper.ProviderMatch(serviceProxy, inputEntity);
            }

            if (inputEntity.Type == revenuetypeos.Upfront.ToString() && !string.IsNullOrEmpty(inputEntity.Opportunity))
            {

                CrmHelper.OpportunityMatch(serviceProxy, inputEntity);
            }

            return inputEntity;
        }
    }
    catch (Exception ex)
    {
        //handle the exception
    }
}


如您所见,它调用5个方法来执行匹配。他们查询5个不同的独立实体。

internal static bool ClientMatch(IOrganizationService crm, EntityViewModel inputEntity)
{
    #region Using Retrieve Multiple

    // Create a column set holding the names of the columns to be retrieved.
    var cols = new ColumnSet("fullname");

    // Create the query.
    var query = new QueryExpression
    {
        EntityName = Xrm.Contact.EntityLogicalName,
        ColumnSet = cols
    };

    query.Criteria.AddCondition("fullname", ConditionOperator.Equal, inputEntity.ClientName);
    query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)ContactState.Active);

    // Create the request object.
    var clientList = crm.RetrieveMultiple(query);

    // If there's not only one existing record in CRM with this key value
    if (recordList == null || recordList.Entities == null || recordList.Entities.Count != 1)
    {
        // if we couldn't find only one record with same key value (maybe none, maybe multiple records)
        query.Criteria.Conditions.Clear();

        query.Criteria.AddCondition("importmetadata", ConditionOperator.Like,
            string.Format("%{0}, {1}, {2}%", inputEntity.ProductName, inputEntity.ProductNumber, inputEntity.ProductProvider));
        query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)ContactState.Active);

        recordList = crm.RetrieveMultiple(query);
    }

    if (recordList != null && recordList.Entities != null && recordList.Entities.Count == 1)
    {
        var client = recordList.Entities[0];

        inputEntity.ClientId = client.Id;
        inputEntity.ClientName = client.Attributes.Contains("fullname") ? client.Attributes["fullname"].ToString() : string.Empty;

        return true;
    }

    return false;

    #endregion Using Retrieve Multiple
}

internal static bool ClientAssetMatch(IOrganizationService crm, EntityViewModel inputEntity)
{
    #region Using Retrieve Multiple

    // Create a column set holding the names of the columns to be retrieved.
    var cols = new ColumnSet(new[] { "assetname", "accountnumber", "revenuecategory" });

    // Build the filter based on the condition.
    var filter = new FilterExpression
    {
        FilterOperator = LogicalOperator.And
    };
    filter.AddCondition("contactid", ConditionOperator.Equal, inputEntity.ClientId);

    // Create a LinkEntity to link the owner's information to the account.
    var link = new LinkEntity
    {
        LinkCriteria = filter,
        LinkFromEntityName = clientasset.EntityLogicalName,
        LinkFromAttributeName = "primaryclient",
        LinkToEntityName = Xrm.Contact.EntityLogicalName,
        LinkToAttributeName = "contactid"
    };

    // Create the query.
    var query = new QueryExpression
    {
        EntityName = clientasset.EntityLogicalName,
        ColumnSet = cols
    };

    query.LinkEntities.Add(link);

    query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)clientassetState.Active);
    query.Criteria.AddCondition("assetname", ConditionOperator.Equal, inputEntity.ProductName);
    query.Criteria.AddCondition("accountnumber", ConditionOperator.Equal, inputEntity.ProductNumber);

    // Create the request object.
    var recordList = crm.RetrieveMultiple(query);

    if (recordList == null || recordList.Entities == null || recordList.Entities.Count != 1)
    {
        // if we couldn't find only one record with same key value (maybe none, maybe multiple records)
        query.Criteria.Conditions.Clear();

        query.Criteria.AddCondition("importmetadata", ConditionOperator.Like,
            string.Format("%{0}, {1}%", inputEntity.ProductName, inputEntity.ProductNumber));
        query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)clientassetState.Active);

        recordList = crm.RetrieveMultiple(query);
    }

    if (recordList.Entities.Count == 1)
    {
        var client = recordList.Entities[0];

        inputEntity.ProductId = client.Id;
        inputEntity.ProductName = client.Attributes.Contains("assetname") ? client.Attributes["assetname"].ToString() : string.Empty;
        inputEntity.ProductNumber = client.Attributes.Contains("accountnumber") ? client.Attributes["accountnumber"].ToString() : string.Empty;
        inputEntity.IsClientAsset = true;

        if (string.IsNullOrEmpty(inputEntity.Category) && client.Attributes.Contains("revenuecategory") && client.Attributes["revenuecategory"] != null)
            inputEntity.Category = GetCategory(((OptionSetValue)client.Attributes["revenuecategory"]).Value);

        return true;
    }

    return false;

    #endregion Using Retrieve Multiple
}

internal static bool InsuranceMatch(IOrganizationService crm, EntityViewModel inputEntity)
{
    #region Using Retrieve Multiple

    // Create a column set holding the names of the columns to be retrieved.
    var cols = new ColumnSet(new[] { "name", "policynumber" });

    // Build the filter based on the condition.
    var filter = new FilterExpression
    {
        FilterOperator = LogicalOperator.And
    };
    filter.AddCondition("contactid", ConditionOperator.Equal, inputEntity.ClientId);

    // Create a LinkEntity to link the owner's information to the account.
    var link = new LinkEntity
    {
        LinkCriteria = filter,
        LinkFromEntityName = personalinsurance.EntityLogicalName,
        LinkFromAttributeName = "individualowner",
        LinkToEntityName = Xrm.Contact.EntityLogicalName,
        LinkToAttributeName = "contactid"
    };

    // Create the query.
    var query = new QueryExpression
    {
        EntityName = personalinsurance.EntityLogicalName,
        ColumnSet = cols
    };

    query.LinkEntities.Add(link);


    query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)personalinsuranceState.Active);
    query.Criteria.AddCondition("name", ConditionOperator.Equal, inputEntity.ProductName);
    query.Criteria.AddCondition("policynumber", ConditionOperator.Equal, inputEntity.ProductNumber);

    // Create the request object.
    var recordList = crm.RetrieveMultiple(query);

    if (recordList == null || recordList.Entities == null || recordList.Entities.Count != 1)
    {
        // if we couldn't find only one record with same key value (maybe none, maybe multiple records)
        query.Criteria.Conditions.Clear();
        query.Criteria.AddCondition("importmetadata", ConditionOperator.Like,
            string.Format("%{0}, {1}%", inputEntity.ProductName, inputEntity.ProductNumber));
        query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)personalinsuranceState.Active);

        recordList = crm.RetrieveMultiple(query);
    }

    if (recordList.Entities.Count == 1)
    {
        var client = recordList.Entities[0];

        inputEntity.ProductId = client.Id;
        inputEntity.ProductName = client.Attributes.Contains("name") ? client.Attributes["name"].ToString() : string.Empty;
        inputEntity.ProductNumber = client.Attributes.Contains("policynumber") ? client.Attributes["policynumber"].ToString() : string.Empty;
        inputEntity.IsClientAsset = false;

        // If it's a personal insurance, it's always an Insurance Revenue Category type
        inputEntity.Category = revenuecategoryos.Insurance.ToString();

        return true;
    }

    return false;

    #endregion Using Retrieve Multiple
}
internal static bool ProviderMatch(IOrganizationService crm, EntityViewModel inputEntity)
{
    #region Using Retrieve Multiple

    // Create a column set holding the names of the columns to be retrieved.
    var cols = new ColumnSet("name");

    // Create the query.
    var query = new QueryExpression
    {
        EntityName = Account.EntityLogicalName,
        ColumnSet = cols
    };

    query.Criteria.AddCondition("name", ConditionOperator.Equal, inputEntity.ProductProvider);
    query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)AccountState.Active);

    // Create the request object.
    var recordList = crm.RetrieveMultiple(query);

    // If there's not only one existing record in CRM with this key value

    if (recordList == null || recordList.Entities == null || recordList.Entities.Count != 1)
    {
        // if we couldn't find only one record with same key value (maybe none, maybe multiple records)
        query.Criteria.Conditions.Clear();

        query.Criteria.AddCondition("importmetadata", ConditionOperator.Like, "%" + inputEntity.ProductProvider + "%");
        query.Criteria.AddCondition("statecode", ConditionOperator.Equal, (int)AccountState.Active);

        recordList = crm.RetrieveMultiple(query);
    }

    if (recordList != null && recordList.Entities != null && recordList.Entities.Count == 1)
    {
        var client = recordList.Entities[0];

        inputEntity.ProductProviderId = client.Id;
        inputEntity.ProductProvider = client.Attributes.Contains("name") ? client.Attributes["name"].ToString() : string.Empty;

        return true;
    }

    return false;

    #endregion Using Retrieve Multiple
}
internal static bool OpportunityMatch(IOrganizationService crm, EntityViewModel inputEntity)
{
    #region Using Retrieve Multiple

    // Create a column set holding the names of the columns to be retrieved.
    var cols = new ColumnSet("name");

    // Create the query.
    var query = new QueryExpression
    {
        EntityName = Opportunity.EntityLogicalName,
        ColumnSet = cols
    };

    query.Criteria.AddCondition("name", ConditionOperator.Equal, inputEntity.Opportunity);
    query.Criteria.AddCondition("statecode", ConditionOperator.NotEqual, (int)OpportunityState.Lost);

    // Create the request object.
    var opportunityList = crm.RetrieveMultiple(query);

    // If there's not only one existing record in CRM with this key value
    if (opportunityList == null || opportunityList.Entities == null || opportunityList.Entities.Count != 1)
    {
        // if we couldn't find only one record with same key value (maybe none, maybe multiple records)
        query.Criteria.Conditions.Clear();

        query.Criteria.AddCondition("importmetadata", ConditionOperator.Like, "%" + inputEntity.Opportunity + "%");
        query.Criteria.AddCondition("statecode", ConditionOperator.NotEqual, (int)OpportunityState.Lost);

        opportunityList = crm.RetrieveMultiple(query);
    }

    if (recordList != null && recordList.Entities != null && recordList.Entities.Count == 1)
    {
        var opportunity = recordList.Entities[0];

        inputEntity.OpportunityId = opportunity.Id;
        inputEntity.Opportunity = opportunity.Attributes.Contains("name") ? opportunity.Attributes["name"].ToString() : string.Empty;

        return true;
    }

    return false;

    #endregion Using Retrieve Multiple
}


通常,此代码适用于少于15行的小型excel文件。但是,当用户输入较大的文件时,性能会非常慢,特别是如果有2个或更多用户同时上传文件(因为整个匹配过程由队列触发的webjob管理)。我尝试实现多任务以同时匹配多个项目,但是没有任何变化。

我一直在想,也许我需要找到某种方法将上述5个功能合并在一起。但是到目前为止,我似乎找不到任何方法可以做到这一点。
接口IOrganizationService的RetrieveMultiple方法似乎一次只能处理一个QueryExpression对象。上面列出的5个实体是单独的。我的问题是可以在一个crm电话中查询它们吗?如果是这样,怎么办?如果没有,是否还有其他方法可以改善性能?我们的客户当然不希望花费超过10分钟的时间来等待匹配过程。他们需要更快的东西。谢谢。

最佳答案

是的,您可以尝试使用ExecuteMultipleRequest类来查看是否可以改善性能。

这是一个示例,该示例在一个多请求中发送四个帐户的RetrieveMultipleRequests和四个联系人的联系人,并打印结果名称。您需要对其进行调整,以处理所需实体的查询,但是查询五个单独的实体应该可以正常工作。

输出:

c# - 是否可以在一个CRM调用中查询多个单独的实体?-LMLPHP

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;

namespace StackOverflow
{
    public class App_ExecuteMultiple
    {
        private IOrganizationService svc;

        public App_ExecuteMultiple(IOrganizationService svc)
        {
            this.svc = svc;
        }

        public void Run()
        {
            var multiReq = new ExecuteMultipleRequest()
            {
                Settings = new ExecuteMultipleSettings()
                {
                    ContinueOnError = true,
                    ReturnResponses = true
                },
                Requests = new OrganizationRequestCollection()
            };

            accountIds().ForEach(i => multiReq.Requests.Add(getAccountRequest(i)));

            contactIds().ForEach(i => multiReq.Requests.Add(getContactRequest(i)));

            var multiResponse = (ExecuteMultipleResponse)svc.Execute(multiReq);

            foreach (var singleResponse in multiResponse.Responses)
            {
                var retrieveResponse = (RetrieveMultipleResponse)singleResponse.Response;

                var attributeName = "";

                var logicalName = retrieveResponse.EntityCollection[0].LogicalName;

                if ( logicalName == "account")
                {
                    attributeName = "name";
                }
                else if (logicalName == "contact")
                {
                    attributeName = "fullname";
                }

                var name = retrieveResponse.EntityCollection[0].GetAttributeValue<string>(attributeName);

                Console.WriteLine(name);
            }
        }

        private RetrieveMultipleRequest getAccountRequest(Guid id)
        {
            return new RetrieveMultipleRequest
            {
                Query = getAccountQuery(id)
            };
        }

        private QueryExpression getAccountQuery(Guid id)
        {
            return new QueryExpression
            {
                EntityName = "account",
                ColumnSet = new ColumnSet(true),
                Criteria = new FilterExpression
                {
                    FilterOperator = LogicalOperator.And,
                    Conditions =
                    {
                        new ConditionExpression
                        {
                            AttributeName = "accountid",
                            Operator = ConditionOperator.Equal,
                            Values = { id }
                        }
                    }
                }
            };
        }

        private List<Guid> accountIds()
        {
            return new List<Guid>
            {
                new Guid("{04C82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{06C82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{08C82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{0AC82C07-98F1-E611-9438-00155D6FD706}")
            };
        }

        private RetrieveMultipleRequest getContactRequest(Guid id)
        {
            return new RetrieveMultipleRequest
            {
                Query = getContactQuery(id)
            };
        }

        private QueryExpression getContactQuery(Guid id)
        {
            return new QueryExpression
            {
                EntityName = "contact",
                ColumnSet = new ColumnSet(true),
                Criteria = new FilterExpression
                {
                    FilterOperator = LogicalOperator.And,
                    Conditions =
                    {
                        new ConditionExpression
                        {
                            AttributeName = "contactid",
                            Operator = ConditionOperator.Equal,
                            Values = { id }
                        }
                    }
                }
            };
        }

        private List<Guid> contactIds()
        {
            return new List<Guid>
            {
                new Guid("{6AC82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{6CC82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{6EC82C07-98F1-E611-9438-00155D6FD706}"),
                new Guid("{70C82C07-98F1-E611-9438-00155D6FD706}")
            };
        }
    }
}

关于c# - 是否可以在一个CRM调用中查询多个单独的实体?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47784908/

10-17 02:46