对于循环运行缓慢

时间:2015-12-10 00:45:03

标签: c# ajax for-loop outlook

我有Web Method查询Outlook以从Global Address List获取所有通讯组列表。

这抓住了超过4,000个分发列表,这正是我想要它做的,但当它进入循环以将4,000个列表传递到我的List时,它需要3分钟才能完成for循环。任何人都可以看到任何与众不同的东西并回答为什么会发生这种情况吗?

这是我的代码:

        public class DistributionListDetails
        {
            public int DistributionListId { get; set; }
            public string DistributionListEmail { get; set; }
        }

        List<DistributionListDetails> distributionLists = new List<DistributionListDetails>();
        int val = 0;

        //create Outlook application. 
        Outlook.Application oApp = new Outlook.Application();

        //get Mapi NameSpace and Logon. 
        Outlook.NameSpace oNS = oApp.GetNamespace("mapi");

        //get Global Address List. 
        Outlook.AddressLists oDLs = oNS.AddressLists;
        Outlook.AddressList oGal = oDLs["Global Address List"];

        //get a specific distribution list. 
        string sDL = "TestDL";
        Outlook.AddressEntries oEntries = oGal.AddressEntries;
        Outlook.AddressEntry oDL = oEntries[sDL];

        if (oDL.Manager != null)
        distributionLists.Add(new DistributionListDetails
            {
                DistributionListId = val,
                DistributionListEmail = oDL.Manager.ToString()
            });

        //get all of the members of the distribution list. 
        oEntries = oDL.Members;
        Outlook.AddressEntry oEntry = default(Outlook.AddressEntry);

        int i = 0;
        for (i = 1; i <= oGal.AddressEntries.Count && i <= 10; i++)
        {
            oEntry = oGal.AddressEntries[i];
            distributionLists.Add(new DistributionListDetails
            {
                DistributionListId = val,
                DistributionListEmail = oEntry.Name
            });
        }

注意:我通过AJAX将循环中返回的列表绑定到下拉列表。

3 个答案:

答案 0 :(得分:1)

假设对AD的查询不是瓶颈,请尝试使用此LINQ for size。它取代了你的最后一个循环。

distributionLists.AddRange(oGal.AddressEntries
  .Cast<Outlook.AddressEntry>()
  .Select(
    x => new DistributionListDetails 
    { 
        DistributionListId = val, 
        DiestributionListEmail = x.Name
    }));

编辑:强制将AddressEntries转换为IQueryable,因此select将起作用。

答案 1 :(得分:0)

I guess you are running this method to grab distribution lists every time someone calls this method. Instead of doing that, it's better to cachce the distribution lists and access them from cache when needed.

  1. Create a repository class for the distribution lists
  2. When a user calls this method for the first time, load the repository from outlook using your method. Then Store it in MemoryCache. You have to select a suitable policy for caching. For an example if, you need to refresh your cached distribution list hourly basis, you have to use absolute expiration and set it to 1hr. If not, you can use sliding expiration which extends the life time of the cached object as users access the lists.
  3. Your repository should first check if the cached object is available, if yes, use it. Else load it again using the above method.

答案 2 :(得分:0)

If you were using C++ or Delphi, you could use AddressEntires.RawTable (returns IMAPITable MAPI object) and use IMAPITable::SetColumns/QueryRows or HrQueryAllRows.

If using Redemption is an option, you could use it MAPITable object. Off the top of my head:

 Redemption.MAPITable table = new Redemption.MAPITable(); 
 table.Item = oGal.AddressEntries;
 ADODB.Recordset recordset = table.ExecSQL("SELECT name from Table");
 while (!recordset.EOF)
 { 
      string name = recordset.Fields(0).Value;
      recordset.MoveNext();
  }