2

Our CRM 2011 database contains approx. 20000 contacts, and I need to loop through all of them using the SDK. Currently I'm finding the following linq query takes a very long time to execute:

Dim contactList = From c In orgService.ContactSet 
  Select New With {
    Key .ContactId = c.ContactId,
    Key .EMailAddress1 = c.EMailAddress1,
    Key .ListIds = From l In c.listcontact_association Select l.ListId
  }

As you can see, I just need a couple of fields from each Contact, and a list of associated Marketing List IDs. Perhaps it's taking a long time because it's doing an additional query (to get the list IDs) within each contact result?

I'm fairly new to Linq, so not sure how the above translates to actual FetchXML communication. Is there a more efficient way of getting that info which would result in shorter query run time?

More Info: I'm writing code to sync a CRM database with a CreateSend database. So I do need to go through all contact records, not only adding to the CS database, but also reflecting changes in list membership and updating activity or other info for each contact where needed. The sync process will eventually run nightly on the CRM server itself, so it's expected to take time to run, but of course I want to make it as efficient as possible.

4

2 回答 2

1

在没有更多信息的情况下,看起来您的查询实际上是两个 - 一个查询用于获取联系人列表,然后另一个查询用于获取列表 ID 列表。这意味着 SQL Server 将返回 20,000 个联系人的完整列表,然后对于每个联系人,您的代码会向 SQL Server 询问相关列表 ID 的列表。

这意味着您要对 SQL Server 进行20,000 + 1次单独调用(尽管这实际上是一个抽象的总数 - CRM SQL 翻译器实际上做的不止这些,但它不会增加显着的开销)。

因此,您真正想要做的只是进行1 个查询来获取您的所有数据,然后开始使用它。我对 VB.NET 的熟练程度不足以进行翻译,但下面的 C# 代码应该可以让你大部分时间到达那里。

// Gets all contacts and list ids in a flat result set
var contacts = from c in orgService.ContactSet
               join lms in orgService.ListMemberSet on c.ContactId equals lms.EntityId.Id into leftJoinedContact
               from ljc in leftJoinedContact.DefaultIfEmpty()
               where ljc.EntityType == Xrm.Contact.EntityLogicalName
               select new
               {
                   c.ContactId,
                   c.EMailAddress1,
                   ljc.ListId
               };

// Calls .ToList() to put the result set in memory
var contactList = contacts.ToList();

// Manipulates the result set in memory, grouping by contact info
var newContactList = contactList.GroupBy(x => new {x.ContactId, x.EMailAddress1})
    .Select(x => new {x.Key.ContactId, x.Key.EMailAddress1, Ids = x.Select(y => y.ListId).ToList()})
    .ToList();

// var contactsWithListIds = newContactList.Where(x => x.Ids.Where(y => y != null).Any()).ToList();
// var contactsWithoutListIds = newContactList.Where(x => x.Ids.Where(y => y != null).Any()).ToList();

foreach (var contact in newContactList)
{
    throw new NotImplementedException();
}
于 2012-06-26T16:36:37.797 回答
0

是的!

但我们需要更多信息。最快的方法是使用直接的 SQL(即过滤视图)。

第二种最快的方法是直接使用 FetchXML(尽管有些人可能会争论 linq 在性能方面与此相当)。

如果您可以过滤查询以将 20,000 条记录减少到只需要的记录,那么您将节省最多的时间。所以我的第一个问题是你为什么要遍历 20,000 条记录?您是否需要全部处理它们,或者您是否需要根据某些标准检查它们,然后根据它们是否符合标准来做一些事情?

于 2012-06-25T17:12:49.760 回答