Post ten dotyczy tematu efektywnego pobierania danych z Active Directory. Załóżmy, że chcemy pobrać listę użytkowników przy czym interesują nas tylko niektóre właściwości, które ich opisują. Pokażę trzy niewiele różniące się z pozoru sposoby odczytania potrzebnych nam danych. Pozornie ponieważ te trzy podejścia znacząco różnią się wydajnością. W celu zademonstrowania różnic napisałem prostą klasę ADTester. Zawiera ona tylko jedną metodę Run w parametrach, której określamy tryb działania oraz liczbę obiektów do pobrania. Różnica pomiędzy trybami jest następująca:
W najlepszym przypadku tryb prosty jest 2.7 szybszy niż tryb normalny i prawie 60 razy szybszy niż tryb wolny. Różnica jest wręcz powalająca, a wnioski nasuwają się same.
- W trybie szybkim (Mode.Fast) dla każdego obiektu z bazy danych Active Directory pobrane zostają tylko wybrane 4 właściwości, a to dzięki zastosowaniu właściwości DirectorySearcher.PropertiesToLoad
- W trybie normalnym (Mode.Normal) dla każdego obiektu z bazy danych Active Directory pobrane zostają wszystkie dostępne dla danego obiektu właściwości.
- W trybie wolnym (Mode.Slow) zamiast użyć danych zawartych w obiektach SearchResult korzystam z metody SearchResult.GetDirectoryEntry.
| maxNumberOfObjects | Mode.Fast | Mode.Normal | Mode.Slow |
| 100 | 363 | 463 | 7507 |
| 200 | 407 | 661 | 1600 |
| 500 | 797 | 2212 | 39323 |
| 1000 | 1353 | 3060 | 75935 |
W najlepszym przypadku tryb prosty jest 2.7 szybszy niż tryb normalny i prawie 60 razy szybszy niż tryb wolny. Różnica jest wręcz powalająca, a wnioski nasuwają się same.
- Jeśli z góry wiemy jakie właściwości nas interesują to używajmy właściwości DirectorySearcher.PropertiesToLoad.
- Korzystajmy z danych zwróconych przez klasę DirectorySearcher w postaci obiektów SearchResult.
- Tylko jeśli to absolutnie konieczne korzystajmy z metody SearchResult.GetDirectoryEntry. Taka potrzeba zachodzi na przykład wtedy jeśli chcemy zmodyfikować dane w AD.
public class ADTester
{
public enum Mode { Fast, Normal, Slow }
public void Run(Mode mode, int maxNumberOfObjects)
{
var ldapPath = "YOUR_LDAP_PATH";
using (var root = new DirectoryEntry(ldapPath))
{
using (var searcher = new DirectorySearcher(root)
{
Filter = "(&(objectClass=user))", SearchScope = SearchScope.Subtree, SizeLimit = maxNumberOfObjects
})
{
if (mode == Mode.Fast)
searcher.PropertiesToLoad.AddRange(new[]{ "displayName","name", "pwdLastSet","userAccountControl" });
using (SearchResultCollection searchResult = searcher.FindAll())
{
foreach (SearchResult user in searchResult)
{
if (mode != Mode.Slow)
{
var displayName = user.Properties["displayName"];
...
}
else
{
var entry = user.GetDirectoryEntry();
var displayName = entry.Properties["displayName"];
...
}
}
}
}
}
}
}
ort: Pokarzę
ReplyDeleteDziękuję za wyłapanie błędu.
ReplyDeleteDzieki!
ReplyDelete