When getting a large number of objects from Active Directory, you should pay special attention to this. When you are not careful, it will fall into the performance bottleneck and even cause memory leakage. This article provides an optimization example for. Net Access to Active Directory.
1. Get the property value of the object directoryentry. Properties
After obtaining a directoryentry object, we start to retrieve its attribute values. Friends who are used to using foreach generally write as follows:
Directoryentry entry = //
Foreach (Property In Entry. properties)
{
If (Property. Name = // )
//
}
In fact, system. directoryservice. propertycollection contains a hashtable used to access key-value pairs. In the indexer, a new propertyvaluecollection object is created for keys not included and added to hashtable.
Therefore, we can safely write down the following:
String Propertname = //
Object Value = Entry. properties [propertname]. value;
For this newly created propertyvaluecolletion, its value attribute definition also ensures the robustness of access. This is itsSource code:
Public Object Value
{
Get
{
If ( Base . Count = 0 )
{
Return Null ;
}
If ( Base . Count = 1 )
{
Return Base . List [ 0 ];
}
Object [] Array = New Object [ Base . Count];
Base . List. copyto (array, 0 );
Return Array;
}
}
In this way,CodeYou do not need to call the entry. properties. Contains method, but directly use the following code to efficiently access the properties of the directoryentry object:
Object Value = Entry. properties [propertyname]. value;
If (Value ! = Null )
{
//
}
In the test, you can save about 90 seconds to query the attribute values of the 20 thousand objects.
2. Build the searcher directorysearcher
Note the following three points when using this class:
(1) cache the search results. Its default cacheresults value is true. If you do not need it, set it to false. Otherwise, a large space will be wasted.
(2) Only search for assigned properties. Propertynamesonly is false by default. it searches for all properties and returns more than the expected objects. Remember to set it to true.
(3) In its constructorSpecify the propertyname array and only search for objects containing propertyname.
The following example shows how to search for objects with the username and password attributes assigned values:
Directorysearcher searcher = New Directorysearcher (
Entry,
" Username = * " ,
New String [] { " Username " , " Password " ,});
Searcher. propertynamesonly = True ;
Searchresultcollection results = Searcher. findall ();
3. traverse and release the result set searchresultcollection
Foreach provides more efficient access to the searchresultcollection because arraylist is used internally in the searchresultcollection to access the collection index. When arraylist is loaded for the first time, it calls the iterator to create and pack all the searchresult objects into arraylist. When searchresultcollection [int Index] is accessed, it unpacks the objects in arraylist. The source code for building innerlist in searchresultcollection is as follows:
Private Arraylist innerlist
{
Get
{
If ( This . Innerlist = Null )
{
This . Innerlist = New Arraylist ();
Ienumerator enumerator = New Resultsenumerator ( This , This . Rootentry. GetUserName (), This . Rootentry. GetPassword (), This . Rootentry. authenticationtype );
While (Enumerator. movenext ())
{
This . Innerlist. Add (enumerator. Current );
}
}
Return This . Innerlist;
}
}
Foreach directly calls the iterator to create and return a searchresult object, avoiding the packing and unpacking process.
Note that: Searchresultcollection is an unmanaged resource and occupies a large amount of memory. When you need to obtain attributes of a large number of objects, we recommend that you use a set to save the required attribute values. After that, you can call searchresultcollection immediately. dispose () to release it. Otherwise, memory leakage may occur.