söndag 17 november 2019

Creating objects with related objects in batch.


I have to admit that I’m slightly ashamed that this is sort of new to me. It probably isn’t a totally new, but I haven’t really used it and it is indeed a very powerful feature of the API in Dynamics 365, whatever it is called today.

There are quite a few questions regarding this.
Hug your related objects
Why isn’t this something that I have used before?
What are the benefits?

Will it work in ExecuteMultiple (is this even a question? I was wondering but whyyyy?)

This dawned a bit on me with the release of the October update from Microsoft. It might have itched a bit even earlier with the input of API throttling but with the October release the API calls was REALLY put in the flashlight since it will not only cause shortages in the use of the API when calls are rejected due to a very chatty world (5000 calls something per 5 minutes rolling time) but now the amount of API calls will cost money in the optimistic scenario and will just stop working completely in the very pessimistic and oh so unlikely scenario. We are still customers to a company that want to make money so there will most probably be a way.

So what part of the October release am I talking about? For many of you it’s obvious that it is the license part of the API calls that is the main focus here. In a “normal” instance of Dynamics-365-not-FinOps-or-similar, the instance will be limited to 20000 API calls per user per day (Enterprise license) and all app users will together share 100000 (100k, and also Enterprise license, at least one) calls per day. The app user calls is a bit unsure if they can be increased, but again Microsoft wants to make money so you will probably be able to do it.

Now since there will be some sort of counter the amount of calls in say an integration needs to be reduced. This is not only good for licensing reasons, but it will, probably, increase the performance as well. We all love the “performance issue meetings” so this might actually be a good thing after all.
I don’t know about you but when creating a set of objects which are linked together I have for the most part created the “main object” first, i.e. the Account, and after that looped through the to be linked objects, say contacts, and created them with the parentcustomerid-field set to the created account. On a good day the linked objects were created using ExecuteMultiple but not always, sometimes because I was lazy and copied the code from a plugin where the ExecuteMultiple wasn’t doing anything good anyway.

Ok Rickard, that was a good half page of loose talk, what are we looking at?


The star of this blog post is RelatedEntities. What on earth is that and when was it introduced, one might ask if one would like to know for how long one should have been ashamed. 

For the introduction, I truly have no clue but I’ve found a question which is pointing to the docs page (https://docs.microsoft.com/en-us/previous-versions/dynamicscrm-2016/developers-guide/gg326824(v=crm.8)?redirectedfrom=MSDN) which is from December 2014 so, maybe since CRM 2015 ish.
 
What is it then? 

This is a collection of entities which are related to the main entity and there is an object on the Entity class which is RelatedEntities. You add these as a key-value pair with a Relationship object as key (which is a slightly weird construct, it’s an object with a string field stating the name of the relationship, why not just have a string? Yes there are other things in there as well but come on…) and an EntityCollection of the related entities.
Creating an account with related contacts looks something like this:

Entity acc = new Entity("account");
            acc.Attributes.Add("name", "test1acc");
            EntityCollection accConts = new EntityCollection();
            Entity cont = new Entity("contact");
            cont.Attributes.Add("firstname", "conttest1f");
            cont.Attributes.Add("lastname", "conttest1l");
            Entity cont2 = new Entity("contact");
            cont2.Attributes.Add("firstname", "conttest2f");
            cont2.Attributes.Add("lastname", "conttest2l");
            accConts.Entities.Add(cont);
            accConts.Entities.Add(cont2);

            acc.RelatedEntities.Add(new KeyValuePair<Relationship, EntityCollection>(new Relationship("contact_customer_accounts"), accConts));
            client.Create(acc);

That’s it, very nice and oh so useable, not only because of the API things happening but it will make some calls quicker.

Back to the questions.

Why haven’t I used it? I just haven’t seen the benefit for some weird reason so I haven’t done my reading, I just have to stop with that. (and start reading)

What are the benefits? Read the article again 😊

Will it work with ExecuteMultiple, yes it can be used since the object created is really the account, or at least the main object. You just add the account to a CreateRequest and add that CreateRequest to the request list in the ExecuteMultiple object and PESTO you have a very nice way of reducing the API calls!


Happy coding.

Rickard Norström
Developer at CRM-Konsulterna
www.crmkonsulterna.se  

torsdag 12 september 2019

Problems publishing workflows on CRM4... on premise

Yes I know, this is a slightly dated software, and by slightly I mean a lot. However, when someone has issues we do what we can to help.

The error message in the trace log says 363: Type System.Workflow.ComponentModel.Serialization.NullExtension is not marked as authorized in the application configuration file

The application says "can't publish workflow" (might have been "can't compile workflow"). This happened earlier and I found  a blog about a lot of authorized types in web.config which solved those. All the old issues could be from a .Net upgrade which I found on a Sharepoint blog.


Regarding this issue, no hits on your favourite search engine to help me. My first thought was to install UR 21 which wasn't installed on the server, however the server was installed with Swedish as base language and Microsoft have removed the UR21 files in Swedish, only English is still availabel, dead end!
Since the last one was solved by adding an authorized type I started looking in the web.config and I actually found a line which looked slightly similar to the error

<authorizedType Assembly="System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Workflow.ComponentModel.Serialization" TypeName="TypeExtension" Authorized="True" />

Sooo, I simply added another line where I changed the TypeName to "NullExtension" and did an IISReset and the old server was publishing workflows again.

Sometimes I just feel that you're not supposed to be doing these things, don't know if it's supported or not but it worked...

Rickard Norström
Developer at CRM-Konsulterna
www.crmkonsulterna.se 

onsdag 21 augusti 2019

How can I find which user is Deployment Administrator?

There’s always the interesting step when you get to handle an on premise CRM that someone else set up. The system was almost always set up a long time ago, which in this case means more than three years, and no one remembers or knows which account that was used to set up the system.
 
What you need to do very often requires you to be deployment administrator, a term which no one knows what it is in the IT department of the customer. That is the normal case.

So, how do you find out which account it is that has the deployment administrator right? The answer is the following query against the MSCRM_CONFIG database:

SELECT * FROM SystemUser WHERE Name IS NOT NULL

It seems that the “Name” column is populated with the account name of the account that is deployment administrator. I’ve had a look at a couple of systems available to me and it has been correct in all of them.


Rickard Norström
Developer at CRM-Konsulterna
www.crmkonsulterna.se