Microsoft Dynamics CRM에서 xlsx 파일의 사용자 입력 데이터를 일치시켜야하는 프로젝트에서 작업하고 있습니다.하나의 CRM 호출에서 여러 개의 개별 엔터티를 쿼리 할 수 있습니까?
나는 일치를 수행하는 방법이 있습니다.
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 명 이상의 사용자가 동시에 파일을 업로드하는 경우 (전체 일치 프로세스가 대기열에서 실행되는 웹 작업에 의해 관리되기 때문에). 내가 동시에 여러 항목을 일치시키기위한 멀티 태스킹을 구현하려고했지만 아무것도 바뀌지 않았습니다.
내가 필요한 것은 위의 5 가지 기능을 병합하는 방법을 찾는 것입니다. 그러나 지금까지 나는 그렇게 할 수있는 방법을 찾을 수없는 것 같습니다. 인터페이스 IOrganizationService의 RetrieveMultiple 메소드는 한 번에 하나의 QueryExpression 객체 만 처리 할 수 있습니다. 위에 나열된 5 개 항목은 별도입니다. 내 질문에 하나의 CRM 호출에서 쿼리 할 수 있습니다? 그렇다면 어떻게? 그렇지 않은 경우 성능을 향상시킬 수있는 다른 방법이 있습니까? 우리 고객은 매칭 프로세스를 기다리기 위해 10 분 이상을 보내고 싶지는 않습니다. 그들은 더 빠른 것을 필요로합니다. 감사.
감사합니다. 문제를 해결할 수 있는지 알려 드리겠습니다. – Anthony
나는 그것을 통합하고있다. 괜찮아 보인다.하지만 여전히 나를 괴롭히는 한 가지는, 하나의 쿼리가 다른 쿼리의 결과에 의존한다면 어떻게 될까? 위의 코드에서 볼 수 있듯이 "CrmHelper.MatchPersonalInsurance (serviceProxy, revenueEntity);"메서드는 " "product"값이 "CrmHelper.MatchClientAsset (serviceProxy, revenueEntity);"메서드에 의해 반환되는 경우에만 실행됩니다. 거짓입니다. 이 RetrieveMultipleRequest 객체가 다른 RetrieveMultipleRequest 객체의 결과에 의존하는지 어떻게 확인할 수 있습니까? – Anthony
먼저 실행해야하는 종속 프로그램이있는 모든 사용자 - 개별적으로 또는 자체 배치로 실행하십시오. 5 개의 쿼리가 있지만 10 분이 걸린다고 생각됩니다. 쿼리하는 하나 이상의 엔티티에 많은 수의 레코드가 있습니까? 또한 기본 제공 대체 키 기능을 살펴볼 수도 있습니다. – Aron