none
PrincipalContext lifetime and caching RRS feed

  • Question

  • What's considered "best practice" when creating and disposing a PrincipalContext? I have an app that makes regular queries to AD, and I've noticed that, depending on the customer's AD configuration, creating a PrincipalContext can take some time—minutes, if the controller is on the other side of the world. I'd like to cache PrincipalContexts in a (static) dictionary, to avoid recreating them every time one is needed, but I wonder what the underlying cost of that practice might be.

    Does a PrincipalContext ever just "go away," because it has a finite lifetime or because the controller reboots, or ... ?

    If PrincipalContext.ConnectedServer is not null, can that be taken as an indication that the PrincipalContext is usable? If not, is there another way of telling whether it's still ok?

    If I don't explicitly Dispose each PrincipalContext, what sort of bad things can I expect to happen?

    Any advice wold be greatly appreciated.

    Friday, February 22, 2013 8:52 PM

Answers

  • When no reply showed up on this thread, I ended up opening an incident and a Microsoft support engineer and I corresponded over a couple of weeks. Here are his replies, slightly edited, including the answers to some follow-up questions that grew out of the exchange:

    In general … do not share the context object … create and destroy it as needed.

    Basically, the PrincipalContext object is an important object in the S.DS.AM world. It maintains the connection information for activity done using it. This means, that if you are going to cache the object and reuse it across multiple threads, then you will need to provide synchronization to prevent two threads from using the same connection information to perform two different actions. Similar to what you have to do if you are sharing a DirectoryEntry object between threads. The object does not have any built in thread synchronization logic.

    As for specific best practices, the same ones that apply to using ADSI in general, apply in this situation.

    Q: If one uses a PrincipalContext object only to retrieve information from AD (user’s group membership, given names, email addresses, etc.), never to modify data, would thread safety still be an issue?

    A: Yes, because the connection information contains the page cookie, this cookie is used to maintain the state of the paged query results and must be protected for a given result set.

    Q: If the application design ensures thread safety but still caches the objects, should one be concerned about a PrincipalContext’s age or inactivity (for example, an assembly that encapsulates the AD logic employed in long-running applications—e.g., an ASP.NET UI app and a Web service—that remain running for at least several weeks at a time)?

    A: ADSI was not designed for long running applications, i.e., applications that run for over 8 to 10 hours.  The primary reason is that the connection caching and reconnect logic is not robust enough to handle all possible situations. We have seen rare instances in which the ADSI connection cache thinks that a connection is good, while the LDAP connection cache will have marked the connection as bad, creating a loop situation, where ADSI tries to reconnect with the same handle, and LDAP keeps rejecting the connection. This state cannot be cleared until the ADSI objects are completely destroyed. The recommendation for long running services is to restart them periodically or design them so that the LDAP connections are used, then completely destroyed periodically.

    • Marked as answer by Rich A Tuesday, July 2, 2013 2:25 PM
    Tuesday, July 2, 2013 2:23 PM

All replies

  • Hi Rich,

    I am trying to involve some other one into this case, please wait it patiently. Thank you.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, February 25, 2013 1:08 PM
    Moderator
  • Would love to know if you ever got an answer for this.

    Micky B

    Tuesday, July 2, 2013 1:38 AM
  • When no reply showed up on this thread, I ended up opening an incident and a Microsoft support engineer and I corresponded over a couple of weeks. Here are his replies, slightly edited, including the answers to some follow-up questions that grew out of the exchange:

    In general … do not share the context object … create and destroy it as needed.

    Basically, the PrincipalContext object is an important object in the S.DS.AM world. It maintains the connection information for activity done using it. This means, that if you are going to cache the object and reuse it across multiple threads, then you will need to provide synchronization to prevent two threads from using the same connection information to perform two different actions. Similar to what you have to do if you are sharing a DirectoryEntry object between threads. The object does not have any built in thread synchronization logic.

    As for specific best practices, the same ones that apply to using ADSI in general, apply in this situation.

    Q: If one uses a PrincipalContext object only to retrieve information from AD (user’s group membership, given names, email addresses, etc.), never to modify data, would thread safety still be an issue?

    A: Yes, because the connection information contains the page cookie, this cookie is used to maintain the state of the paged query results and must be protected for a given result set.

    Q: If the application design ensures thread safety but still caches the objects, should one be concerned about a PrincipalContext’s age or inactivity (for example, an assembly that encapsulates the AD logic employed in long-running applications—e.g., an ASP.NET UI app and a Web service—that remain running for at least several weeks at a time)?

    A: ADSI was not designed for long running applications, i.e., applications that run for over 8 to 10 hours.  The primary reason is that the connection caching and reconnect logic is not robust enough to handle all possible situations. We have seen rare instances in which the ADSI connection cache thinks that a connection is good, while the LDAP connection cache will have marked the connection as bad, creating a loop situation, where ADSI tries to reconnect with the same handle, and LDAP keeps rejecting the connection. This state cannot be cleared until the ADSI objects are completely destroyed. The recommendation for long running services is to restart them periodically or design them so that the LDAP connections are used, then completely destroyed periodically.

    • Marked as answer by Rich A Tuesday, July 2, 2013 2:25 PM
    Tuesday, July 2, 2013 2:23 PM
  • Was there ever any follow up to this thread?  If so, can you repost the outcome and/or links to the info?
    Tuesday, November 24, 2015 8:46 PM