使用 C# 在 Dynamics CRM 中合并联系人
Merge Contacts in Dynamics CRM using C#
所以我正在编写一个控制台应用程序,用于合并 CRM 部署中的重复联系人。
这段代码分为两部分。获取重复记录的 GUID 的部分和进行实际合并的部分。我的问题出在前者。
我使用客户的 phone 号码来检查唯一性,正如您在代码中看到的那样,并且有一个 txt 文件,每个号码都换行。
我需要填写此文本文件中的联系人列表并将其传递给合并方法。
我可以定义一个硬编码的字符串,它可以那样工作,但是
实际执行合并的部分有效,但将所有这些重复项填充到列表中并传递它的部分无效。我试着把它当作一个字符串列表来填充,但显然这不是它处理联系人的方式。
下面包含代码。
using System;
using System.ServiceModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Zeno.Business;
using Zeno.Configuration;
using Zeno.CRMEntityModel;
using System.Collections.Generic;
using System.IO;
namespace MergeTool
{
public static class MergeContact
{
public static ContactBL bl = new ContactBL();
/// <param name="serverConfig">Contains server connection information.</param>
/// <param name="promptForDelete">When True, the user will be prompted to delete
/// all created entities.</param>
public static void Merge()
{
List<Contact> contactList = getAccountGuids();
for (int i = 0; i < contactList.Count; i++)
{
Contact contact = contactList[0];
Contact _subContact = contactList[1];
EntityReference target = new EntityReference();
target.Id = contact.ContactId.Value;
target.LogicalName = Contact.EntityLogicalName;
MergeRequest merge = new MergeRequest();
merge.SubordinateId = _subContact.ContactId.Value;
merge.Target = target;
merge.PerformParentingChecks = false;
Contact updateContent = new Contact();
updateContent.zeno_nebimcustomernumber = _subContact.zeno_nebimcustomernumber;
//updateContent....
if (string.IsNullOrEmpty(contact.FirstName))
{
updateContent.FirstName = _subContact.FirstName;
}
//further if conditions clipped for brevity
merge.UpdateContent = updateContent;
MergeResponse merged = (MergeResponse)bl.Execute(merge);
}
}
public static List<Contact> getAccountGuids()
{
//TO DO
// Get all duplicate contact mobile phone numbers
string mobilePhone = "+90(505)220 72 29";
return bl.RetrieveContactListByMobilePhone(mobilePhone);
}
}
}
应要求,我在下面包含了 ContactsBL 的内容。
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Zeno.CRMEntityModel;
using Zeno.Repository;
namespace Zeno.Business
{
public class ContactBL:BLBase
{
private ContactRepository contactRepository;
public ContactBL()
: base()
{
}
public ContactBL(IOrganizationService service)
: base(service)
{
}
public Guid CheckPhoneNumber(string phoneNumber)
{
this.contactRepository = new ContactRepository(this.Connection);
return contactRepository.CheckPhoneNumber(phoneNumber);
}
public List<Contact> RetrieveContactListByMobilePhone(string phoneNumber)
{
this.contactRepository = new ContactRepository(this.Connection);
return contactRepository.RetrieveContactListByMobilePhone(phoneNumber);
}
}
}
有一种更好的查找重复项的方法。在 CRM 中创建重复检测规则,然后从 C# 中,您可以向 CRM 发送请求以取回重复项(它将使用这些规则为您查找重复项)。这是最简单的方法。
以下摘录自MSDN:
// PagingInfo is Required.
var request = new RetrieveDuplicatesRequest
{
BusinessEntity = new Account { Name = "Microsoft" }.ToEntity<Entity>(),
MatchingEntityName = Account.EntityLogicalName,
PagingInfo = new PagingInfo() { PageNumber = 1, Count = 50 }
};
Console.WriteLine("Retrieving duplicates");
var response =(RetrieveDuplicatesResponse)_serviceProxy.Execute(request);
for (int i = 0; i < response.DuplicateCollection.Entities.Count; i++)
{
var crmAccount = response.DuplicateCollection.Entities[i].ToEntity<Account>();
Console.WriteLine(crmAccount.Name + ", " + crmAccount.AccountId.Value.ToString());
}
看来您忘记了 i
。
您不想在主循环中使用索引 0
和 1
,因为那样会一遍又一遍地合并前两个实体。您应该改用迭代器变量 i
。
而不是用绝对索引初始化你的联系人:
Contact contact = contactList[0];
Contact _subContact = contactList[1];
您应该使用迭代器变量。
Contact contact = contactList[i];
Contact _subContact = contactList[i+1];
更新:可能 IndexOutOfBoundsException
当心 IndexOutOfBoundsException 可能会因 contactList[i+1]
引用而抛出。您应该通过与 contactList.Count - 1
而不是 contaclist.Count
进行比较来避免这种情况。 :
// BAD! : contactList[i+1] would throw IndexOutOfBoundsException on the last cycle.
for(int i=0; i < contactList.Count; i++)
// GOOD : contactList[i+1] would point to the last item in the last cycle so it should be okay.
for(int i=0; i < contactList.Count - 1; i++)
所以我正在编写一个控制台应用程序,用于合并 CRM 部署中的重复联系人。
这段代码分为两部分。获取重复记录的 GUID 的部分和进行实际合并的部分。我的问题出在前者。
我使用客户的 phone 号码来检查唯一性,正如您在代码中看到的那样,并且有一个 txt 文件,每个号码都换行。
我需要填写此文本文件中的联系人列表并将其传递给合并方法。
我可以定义一个硬编码的字符串,它可以那样工作,但是
实际执行合并的部分有效,但将所有这些重复项填充到列表中并传递它的部分无效。我试着把它当作一个字符串列表来填充,但显然这不是它处理联系人的方式。
下面包含代码。
using System;
using System.ServiceModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Zeno.Business;
using Zeno.Configuration;
using Zeno.CRMEntityModel;
using System.Collections.Generic;
using System.IO;
namespace MergeTool
{
public static class MergeContact
{
public static ContactBL bl = new ContactBL();
/// <param name="serverConfig">Contains server connection information.</param>
/// <param name="promptForDelete">When True, the user will be prompted to delete
/// all created entities.</param>
public static void Merge()
{
List<Contact> contactList = getAccountGuids();
for (int i = 0; i < contactList.Count; i++)
{
Contact contact = contactList[0];
Contact _subContact = contactList[1];
EntityReference target = new EntityReference();
target.Id = contact.ContactId.Value;
target.LogicalName = Contact.EntityLogicalName;
MergeRequest merge = new MergeRequest();
merge.SubordinateId = _subContact.ContactId.Value;
merge.Target = target;
merge.PerformParentingChecks = false;
Contact updateContent = new Contact();
updateContent.zeno_nebimcustomernumber = _subContact.zeno_nebimcustomernumber;
//updateContent....
if (string.IsNullOrEmpty(contact.FirstName))
{
updateContent.FirstName = _subContact.FirstName;
}
//further if conditions clipped for brevity
merge.UpdateContent = updateContent;
MergeResponse merged = (MergeResponse)bl.Execute(merge);
}
}
public static List<Contact> getAccountGuids()
{
//TO DO
// Get all duplicate contact mobile phone numbers
string mobilePhone = "+90(505)220 72 29";
return bl.RetrieveContactListByMobilePhone(mobilePhone);
}
}
}
应要求,我在下面包含了 ContactsBL 的内容。
using Microsoft.Xrm.Sdk;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Zeno.CRMEntityModel;
using Zeno.Repository;
namespace Zeno.Business
{
public class ContactBL:BLBase
{
private ContactRepository contactRepository;
public ContactBL()
: base()
{
}
public ContactBL(IOrganizationService service)
: base(service)
{
}
public Guid CheckPhoneNumber(string phoneNumber)
{
this.contactRepository = new ContactRepository(this.Connection);
return contactRepository.CheckPhoneNumber(phoneNumber);
}
public List<Contact> RetrieveContactListByMobilePhone(string phoneNumber)
{
this.contactRepository = new ContactRepository(this.Connection);
return contactRepository.RetrieveContactListByMobilePhone(phoneNumber);
}
}
}
有一种更好的查找重复项的方法。在 CRM 中创建重复检测规则,然后从 C# 中,您可以向 CRM 发送请求以取回重复项(它将使用这些规则为您查找重复项)。这是最简单的方法。
以下摘录自MSDN:
// PagingInfo is Required.
var request = new RetrieveDuplicatesRequest
{
BusinessEntity = new Account { Name = "Microsoft" }.ToEntity<Entity>(),
MatchingEntityName = Account.EntityLogicalName,
PagingInfo = new PagingInfo() { PageNumber = 1, Count = 50 }
};
Console.WriteLine("Retrieving duplicates");
var response =(RetrieveDuplicatesResponse)_serviceProxy.Execute(request);
for (int i = 0; i < response.DuplicateCollection.Entities.Count; i++)
{
var crmAccount = response.DuplicateCollection.Entities[i].ToEntity<Account>();
Console.WriteLine(crmAccount.Name + ", " + crmAccount.AccountId.Value.ToString());
}
看来您忘记了 i
。
您不想在主循环中使用索引 0
和 1
,因为那样会一遍又一遍地合并前两个实体。您应该改用迭代器变量 i
。
而不是用绝对索引初始化你的联系人:
Contact contact = contactList[0];
Contact _subContact = contactList[1];
您应该使用迭代器变量。
Contact contact = contactList[i];
Contact _subContact = contactList[i+1];
更新:可能 IndexOutOfBoundsException
当心 IndexOutOfBoundsException 可能会因 contactList[i+1]
引用而抛出。您应该通过与 contactList.Count - 1
而不是 contaclist.Count
进行比较来避免这种情况。 :
// BAD! : contactList[i+1] would throw IndexOutOfBoundsException on the last cycle.
for(int i=0; i < contactList.Count; i++)
// GOOD : contactList[i+1] would point to the last item in the last cycle so it should be okay.
for(int i=0; i < contactList.Count - 1; i++)