Bulk Contact Import API

2025/09/05 4:07 PM

I am building some code to import contact data from a separate site.

When I create a Kentico contact, I'm just setting the basic data such as email, first/last name, company name, etc.

When I do a bulk insert, it throws SQL errors about some of the fields that are usually automatically set, such as ContactCreated.

But if I fall back to inserting them one-by-one, it works fine.

Here's an example similar to what I'm doing:

//'contacts' at this point is a List<ContactInfo> of uncommitted contacts (with basic member data populated)

try
{
    ContactInfo.Provider.BulkInsert(contacts, new BulkInsertSettings
    {
        // BatchSize = context.BatchSize,
        Options = SqlBulkCopyOptions.Default
    });
}
catch (Exception ex)
{
    //fallback to single insert
    foreach (var contact in contacts)
    {
        await ContactInfo.Provider.SetAsync(contact);
    }
}

In this example, it'll always fall back to the single-insert version unless you populate every value, and the single-insert version works and populates those fields on its own.

Is there a BulkInsertSettings parameter, or something like that, that will cause the bulk insert to run whatever 'additional' logic is happening in the single-user version?

I'm doing the same thing with ContactGroupMemberInfo and EmailSubscriptionConfirmationInfo, so I'm worried that there are side effects that I'll run into by using the Bulk Insert for the three of these.
There are tens of thousands of contacts and subscriptions, which is why I want to use bulk.

Tags:
Email marketing v30.8.0 ASP.NET Core C#

Answers

2025/09/05 9:05 PM
Accepted answer

Based on the Contacts Importer, the answer is in fact to just directly insert datetime.now into the value.

And for adding them to a recipient list (ContactGroupMemberInfo), it indicates to just use a custom query because matching based on contactID/ContactGUID is too long for a where clause and Kentico ObjectQuery can't seem to handle filtering on JSON lists (OPENJSON()).

Both of the above are in ImportService.cs

The importer doesn't seem to do this next part, but don't forget to create an EmailSubscriptionConfirmation for each ContactGroupMemberInfo record, or else they won't actually show up as receiving emails in the Recipient List. The same sort of custom query logic can be used to join to the OM_Contact table and get the confirmation via OPENJSON(), just remember you'll also have to make up a guid for the Confirmation Guid ID, since you're skipping Kentico's Set() logic. You can just do this in your custom query:

GetDate() AS [{nameof(EmailSubscriptionConfirmationInfo.EmailSubscriptionConfirmationDate)}],
NEWID() AS [{nameof(EmailSubscriptionConfirmationInfo.EmailSubscriptionConfirmationGUID)}]

To response this discussion, you have to login first.