I'm trying to move a whole load of users from 1 business unit to a newly setup 1. I'm not a CRM expert by any means, and I've been informed that to move the users we need to store their existing roles first, then move them to the new BU and then restore their roles that aren't BU specific and then modify the ones that are. An example for a user would be:
BU1
Roles:
BU1Admin
BU1Read-Only
Contracts
Move these to:
BU2
Roles:
BU2Admin
BU2Read-Only
Contracts
So in this example the user would need to have their admin role and read-only role modified to BU2 but the contracts one stays the same. My initial thought was to construct a query to retrieve the systemuserid's along with the role names using something like this:
Dictionary<Guid, string> UserRoles = new Dictionary<Guid, string>();
QueryExpression query = new QueryExpression();
query.EntityName = "systemuserroles";
ColumnSet cols = new ColumnSet();
cols.Attributes = new string[] { "systemuserid", "roleid" };
query.ColumnSet = cols;
LinkEntity le = new LinkEntity();
le.LinkFromEntityName = "systemuserroles";
le.LinkFromAttributeName = "roleid";
le.LinkToEntityName = "role";
le.LinkToAttributeName = "roleid";
LinkEntity le2 = new LinkEntity();
le2.LinkFromEntityName = "systemuserroles";
le2.LinkFromAttributeName = "systemuserid";
le2.LinkToEntityName = "systemuser";
le2.LinkToAttributeName = "systemuserid";
// Find only users in BU1
ConditionExpression ce = new ConditionExpression();
ce.AttributeName = "businessunitid";
ce.Operator = ConditionOperator.Equal;
ce.Values = new string[] { BU1 Guid };
le2.LinkCriteria = new FilterExpression();
le2.LinkCriteria.Conditions = new ConditionExpression[] { ce };
query.LinkEntities = new LinkEntity[] { le, le2 };
try
{
//This call doesn't work and fails saying RetrieveMultiple doesn't support entities of type systemuserroles.
BusinessEntityCollection UserRolesCollection = crmService.RetrieveMultiple(query);
foreach (BusinessEntity be in UserRolesCollection.BusinessEntities)
{
//Do my stuff here
}
}
catch (SoapException se)
{
throw new Exception("Error occurred." + se.Detail);
}
The next step, which I want to be able to do is then update the users with the new roles. I don't even know if this can be done based on the problems I'm having with the above. Any help would be much appreciated. I'm wondering if DynamicEntity would be of any use here after reading this?
UPDATE:
It looks like you can update a users roles using the AssignUserRolesRole Request class here. However, I'm still stuck on the retrieval bit at the moment as well. I'm wondering if I need to resort to sql?
I finally managed to find a way to do it through the API. It's essentially 2 queries, 1 to get the systemuserid of all the users and the second to get the roleids for each systemuserid. This will give me the current roles of all the users.
I create a dictionary that maps the old roles guids to the new roles guids.
I then change their business unit, which gets rid of all their roles, and using the dictionary and previously stored user roles I can then map to the new roles for each user. I came up with this code for anyone in a similar situation:
To store the roles for each user I've created a class called UserRoles:
NOTE: This has not been fully tested, but does seem to do what I want, which is allow me to move a user to a different BU and set new roles for them based on their old ones.
Here is an unsupported SQL solution for moving your users. I just tried it out and everything seems to work fine. You could try it out in a dev environment first to prove it works or it might be a starting point for your hybrid solution.