2015-08-20 3 views
1

Следующий код позволяет мне извлечь весь глобальный список адресов из DirectoryServices. Код функционирует так, что он дает мне то, что мне нужно. Проблема в том, что для возврата 1000 объектов требуется около 20 секунд. Есть ли что-то, что я могу сделать, чтобы ускорить это?Извлечение глобального списка адресов из DirectoryServices чрезвычайно медленное

public static List<Address> GetGlobalAddressList() 
    { 
     using (var searcher = new DirectorySearcher()) 
     { 
      using (var entry = new DirectoryEntry(searcher.SearchRoot.Path, "*****", "*****")) 
      { 
       searcher.Filter = "(&(mailnickname=*)(objectClass=user))"; 
       searcher.PropertiesToLoad.Add("cn"); 
       searcher.PropertyNamesOnly = true; 
       searcher.SearchScope = SearchScope.Subtree; 
       searcher.Sort.Direction = SortDirection.Ascending; 
       searcher.Sort.PropertyName = "cn"; 
       var results = searcher.FindAll(); 
       var addressList = new List<Address>(); 
       foreach (SearchResult i in results) 
       { 
        var address = new Address 
        { 
         DisplayName = (string)i.GetDirectoryEntry().Properties["displayName"].Value, 
         Mail = (string) i.GetDirectoryEntry().Properties["mail"].Value 
        }; 
        addressList.Add(address); 

       } 
       return addressList; 
      } 
     } 
    } 

    public class Address 
    { 
     public string DisplayName { get; set; } 
     public string Mail { get; set; } 

    } 
+0

Возможно, профилировщик может определить узкие места? –

ответ

0

Оказалось, что проблема GetDirectoryEntry(). Очевидно, что использование этого ресурса очень ресурсоемкое, потому что оно позволяет вам фактически обновить запись в каталоге после ее получения. Другими словами, каждый вызов этого вызова вызывает дополнительный вызов активного каталога каждый раз, когда он вызывается. Мне просто нужно получить доступ/прочитать свойства, не обновляя их, поэтому я переписал метод без GetDirectoryEntry(). Теперь он мгновенно возвращает весь глобальный список адресов. Код, который решил мою проблему, приведен ниже.

[WebMethod()] 
    public static List<Address> GetAddresses() 
    { 
     using (var objsearch = new DirectorySearcher()) 
     { 
      objsearch.Filter = "(& (mailnickname=*)(objectClass=user))"; 
      objsearch.SearchScope = SearchScope.Subtree; 
      objsearch.PropertiesToLoad.Add("cn");     
      objsearch.PropertiesToLoad.Add("mail"); 
      objsearch.PropertyNamesOnly = false; 
      objsearch.Sort.Direction = SortDirection.Ascending; 
      objsearch.Sort.PropertyName = "cn"; 
      objsearch.PageSize = 5000; 
      var colresults = objsearch.FindAll(); 
      var addressList = new List<Address>(); 
      foreach (SearchResult objresult in colresults) 
      { 
       var address = new Address(); 

       var cn = objresult.Properties["cn"]; 
       if (cn.Count >= 1) address.DisplayName = (cn[0]) as string; 

       var mail = objresult.Properties["mail"]; 
       if (mail.Count >= 1) address.Mail = (mail[0]) as string; 

       addressList.Add(address); 
      } 
      return addressList; 
     } 

    } 
0

Из вашего кода я вижу, что вы возвращаете полностью заполненный список. Вы можете изменить этот метод на возвращаемые значения yeild, как только они будут идентифицированы. Для этого измените тип возвращаемого значения из списка в Ienumerable, затем удалите возвращаемый список и добавьте его в этот список, возвращайте вновь созданный объект с возвратом yeild

dotnetperls имеет отличное определение для выражения yeild.

Вы будете иметь что-то вроде этого ...

public static IEnumerable<Address> GetGlobalAddressList() 
{ 
    using (var searcher = new DirectorySearcher()) 
    { 
     using (var entry = new DirectoryEntry(searcher.SearchRoot.Path, "*****", "*****")) 
     { 
      searcher.Filter = "(&(mailnickname=*)(objectClass=user))"; 
      searcher.PropertiesToLoad.Add("cn"); 
      searcher.PropertyNamesOnly = true; 
      searcher.SearchScope = SearchScope.Subtree; 
      searcher.Sort.Direction = SortDirection.Ascending; 
      searcher.Sort.PropertyName = "cn"; 

      foreach (SearchResult i in searcher.FindAll()) 
      { 
       var address = new Address 
       { 
        DisplayName = (string)i.GetDirectoryEntry().Properties["displayName"].Value, 
        Mail = (string) i.GetDirectoryEntry().Properties["mail"].Value 
       }; 
       yeild return address; 
      } 
     } 
    } 
} 

Вы должны также проверить Joes принятый ответ.

+0

Я дам этот снимок завтра. – TimidObserver

+0

Я пробовал это, и он не увеличивал скорость метода вообще. Спасибо за предложение. – TimidObserver

+0

Стоит убедиться, что, когда вы вызываете метод, вы не называете ToList(), так как это снова блокирует выполнение до тех пор, пока все элементы не будут восстановлены. –