Our Active Directory groups are containing 500k users, one even more than a million users.
We are adding and removing users from groups using the System.DirectoryServices.AccountManagement
namespace, as described here: https://stackoverflow.com/a/2143742/1099519
The code itself works perfectly fine, besides the fact that is super slow, adding a user takes up to a minute, sometimes even more!
I could figure out the following line of code, seems to trigger a lazy load mechanism in .net:
adGroupPrincipal.Members.Add(userPrincipal);
I used Wireshark to see what's happening, when calling GroupPrincipal.Members.Add(UserPrincipal)
and I saw a lot of network traffic. My assumption: Accessing the Members property triggers a lazy load method to get all members of a group.
In the official documentation of the Members
-property (https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.groupprincipal.members(v=vs.110).aspx) is no information of its behavior.
Comparing adding a user the "old school" way with DirectoryEntry
of the System.DirectoryServices
namespace as such:
DirectoryEntry groupEntry = new DirectoryEntry("LDAP://server/CN=GROUPNAME,OU=Groups,OU=_CUSTOMERS,DC=srv,DC=tld", "USERNAME", "PASSWORD");
string userDn = String.Concat("LDAP://server/CN=", samAccountName, ",OU=Groups,OU=_CUSTOMERS,DC=srv,DC=tld"));
groupEntry.Invoke("Add", new object[] { userDn });
groupEntry.CommitChanges();
That takes roughly 50ms.
Note that the Invoke("Add", new object[] { userDn })
method I used, was recommend in this Stackoverflow article Server is unwilling to process the request - Active Directory - Add User via C# in order to avoid the "Server is unwilling to process the request" exception
So basically my workaround does the job, but somehow I am not 100% happy, as I actually prefer to use the System.DirectoryServices.AccountManagement
namespace, any ideas how to avoid the performance issue using that namespace?