2015-08-20 28 views
1

以下代碼允許我從DirectoryServices中提取整個全局地址列表。代碼的功能在於它給了我所需要的東西。問題是大約需要20秒才能返回1000個對象。有什麼我可以做的,以加快速度?從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

從你的代碼中,我可以看到你正在返回一個完全填充的列表。您可以修改此方法,只要它們被識別,就立即返回值。爲此,將List的返回類型更改爲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(),因爲這將再次阻塞執行,直到所有項目都被檢索。 –