3

I'm using the Dynamics connector in Azure Data Factory.

TLDR

Does this connector support loading child records which need a parent record key passed in? For example if I want to create a contact and attach it to a parent account, I upsert a record with a null contactid, a valid parentcustomerid GUID and set parentcustomeridtype to 1 (or 2) but I get an error.

Long Story

I'm successfully connecting to Dynamics 365 and extracting data (for example, the lead table) into a SQL Server table

To test that I can transfer data the other way, I am simply loading the data back from the lead table into the lead entity in Dynamics.

I'm getting this error:

Failure happened on 'Sink' side. ErrorCode=DynamicsMissingTargetForMultiTargetLookupField,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=,Source=,''Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=Cannot find the target column for multi-target lookup field: 'ownerid'.

As a test I removed ownerid from the list of source columns it loads OK.

This is obviously a foreign key value.

It raises two questions for me:

  1. Specifically with regards to the error message: If I knew which lookup it needed to use, how can I specify which lookup table it should validate against? There's no settings in the ADF connector to allow me to do this.

  2. This is obviously a foreign key value. If I only had the name (or business key) for this row, how can I easily lookup the foreign key value?

How is this normally done through other API's, i.e. the web API?

Is there an XRMToolbox addin that would help clarify?

I've also read some posts that imply that you can send pre-connected data in an XML document so perhaps that would help also.

EDIT 1

I realised that the lead.ownertypeid field in my source dataset is NULL (that's what was exported). It's also NULL if I browse it in various Xrmtoolbox tools. I tried hard coding it to systemuser (which is what it actually is in the owner table against the actual owner record) but I still get the same error.

I also notice there's a record with the same PK value in systemuser table

So the same record is in two tables, but how do I tell the dynamics connector which one to use? and why does it even care?

EDIT 2

I was getting a similar message for msauto_testdrive for customerid.

I excluded all records with customerid=null, and got the same error.

EDIT 2

This link appears to indicate that I need to set customeridtype to 1 (Account) or 2 (Contact). I did so, but still got the same error.

Also I believe I have the same issue as this guy.

Maybe the ADF connector suffers from the same problem.

Nick.Mc
  • 18,304
  • 6
  • 61
  • 91
  • ownerid is special field and can reference more than one table. Thats why there is owneridtype see https://learn.microsoft.com/en-us/dynamics365/customer-engagement/web-api/ownershiptypes?view=dynamics-ce-odata-9 – minohimself May 30 '20 at 16:11
  • I really do appreciate your response. The error certainly indicates that it requires more information to disambiguate. It doesn't appear that the ADF dynamics connector allows this though. – Nick.Mc May 31 '20 at 03:12
  • I would create microsoft ticket. maybe its a "feature" – minohimself May 31 '20 at 06:30
  • I think it's more a lack of features. I'm beginning to realise that dynamics integrations are far more complicated than loading tables. I don't the ADF connector is functional enough to be of any use. – Nick.Mc May 31 '20 at 08:38

2 Answers2

5

At the time of writing, @Arun Vinoth was 100% correct. However shortly afterwards there was a documentation update (in response to a GitHub I raised) that explained how to do it.

I'll document how I did it here.

To populate a contact with against a parent account, you need the parent accounts GUID. Then you prepare a dataset like this:

SELECT 
-- a NULL contactid means this is a new record
CAST(NULL as uniqueidentifier) as contactid,
-- the GUID of the parent account
CAST('A7070AE2-D7A6-EA11-A812-000D3A79983B' as uniqueidentifier) parentcustomerid,
-- customer id is an account
'account' [parentcustomerid@EntityReference],
'Joe' as firstname,
'Bloggs' lastname,

Now you can apply the normal automapping approach in ADF.

Now you can select from this dataset and load into contact. You can apply the usual automapping approach, this is: create datasets without schemas. Perform a copy activity without mapping columns

Nick.Mc
  • 18,304
  • 6
  • 61
  • 91
  • 1
    Now if only there was a way to use EntityReferences that point to an alternate key instead of the GUID for the parent record... – Oliver Rahner Jul 15 '20 at 18:14
  • I’m trying to use alternate keys right now. I raised a GitHub because it returns an error. – Nick.Mc Jul 15 '20 at 21:32
  • @OliverRahner I'm trying to do exactly that right now. I raised this doc github but I'm also going to ask a question in here and on Q&A https://github.com/MicrosoftDocs/azure-docs/issues/59028 If you are facing the same problem, your input would be appreciated. – Nick.Mc Jul 15 '20 at 22:54
  • 1
    If anyone is interested. I built a process that simply pulls that entire table back into the database so you can join to that table on the alternate key to lookup the internal GUID. The CDS connector pulls data back pretty quick (especially when it's only key columns) – Nick.Mc Aug 24 '20 at 05:06
  • 1
    @Nick.NcDermaid That is exactly what I did... Additonally, there is a feature request for this on Azure Feedback: https://feedback.azure.com/forums/270578-data-factory/suggestions/40687474-common-data-service-connector-alternate-key-suppo – Oliver Rahner Aug 25 '20 at 07:14
  • I would totally vote that up if I could work out how to log in :/ – Nick.Mc Aug 25 '20 at 07:15
  • Actually perhaps we could "collabarate" in some way. I'm loading data into D365 via ADF and having lots of API throttling issues etc. It's quite an effort to get all of this working. I'd be interested in seeing what you're up to. – Nick.Mc Aug 25 '20 at 07:17
  • This was part of a customer's project which is closed now, so I don't have any ongoing work. Our goal was to interface with their legacy system which is hosted on an on prem SQL server, one way to D365. The only entities we touched were Account, Address and Quote. Apart from this single issue (and finding out about how to work with the intitial question regarding EntityReference) everything else went pretty smooth. We aren't close to any amount of data that will cause throttling, so I probably can't help you there. – Oliver Rahner Aug 26 '20 at 09:09
2

This is the ADF limitation with respect to CDS polymorphic lookups like Customer and Owner. Upvote this ADF idea

Workaround is to use two temporary source lookup fields (owner team and user in case of owner, account and contact in case of customer) and with parallel branch in a MS Flow to solve this issue. Read more, also you can download the Flow sample to use.

  • First, create two temporary lookup fields on the entity that you wish to import Customer lookup data into it, to both the Account and Contact entities respectively
  • Within your ADF pipeline flow, you will then need to map the GUID values for your Account and Contact fields to the respective lookup fields created above. The simplest way of doing this is to have two separate columns within your source dataset – one containing Account GUID’s to map and the other, Contact.
  • Then, finally, you can put together a Microsoft Flow that then performs the appropriate mapping from the temporary fields to the Customer lookup field. First, define the trigger point for when your affected Entity record is created (in this case, Contact) and add on some parallel branches to check for values in either of these two temporary lookup fields

enter image description here

  • Then, if either of these conditions is hit, set up an Update record task to perform a single field update, as indicated below if the ADF Account Lookup field has data within it
  • I really appreciate your response. I've raised a github request on the doco page to make it clear that this connector is basically unusable for core CDM entities like *contact*. I've wasted a lot of time on this and now I need to find a new approach. – Nick.Mc Jun 09 '20 at 22:09
  • @Nick.McDermaid, MS docs need improvements most of the time. In this case it can be more detailed than just mentioned Lookup datatype mapping as “with single target associated” in docs: https://learn.microsoft.com/en-us/azure/data-factory/connector-dynamics-crm-office-365#data-type-mapping-for-dynamics – Arun Vinoth-Precog Tech - MVP Jun 09 '20 at 23:12
  • Agreed - technically it does point out that it's not supported, but I think it's reasonable, given all the MS hype about CDM and CDS, that it should be made more obvious that the connector does not support upserting core entities like Contact. Again thanks for your help it means I can stop chasing this option and try something else. – Nick.Mc Jun 09 '20 at 23:15
  • 1
    My colleague found this link https://learn.microsoft.com/en-us/azure/data-factory/connector-dynamics-crm-office-365#writing-data-to-lookup-field which appears to indicate that it is possible. I'll be testing it tomorrow – Nick.Mc Jun 11 '20 at 08:01
  • @Nick.McDermaid I believe it’s the same link I shared earlier, probably MS updated it after your GitHub issue – Arun Vinoth-Precog Tech - MVP Jun 11 '20 at 10:41
  • 1
    Yes you're right, I didn't realise that - it is the same link and yes they've just updated it - I can see in the document commits! – Nick.Mc Jun 11 '20 at 13:09